diff --git a/dataplane/forwarding/fwdport/ports/kernel.go b/dataplane/forwarding/fwdport/ports/kernel.go index f18fa927..ecc42c63 100644 --- a/dataplane/forwarding/fwdport/ports/kernel.go +++ b/dataplane/forwarding/fwdport/ports/kernel.go @@ -190,13 +190,20 @@ func (kernelBuilder) Build(portDesc *fwdpb.PortDesc, ctx *fwdcontext.Context) (f return nil, fmt.Errorf("failed to set arp_ignore to 2: %v", err) } - netlink.LinkSetUp(l) + if err := netlink.LinkSetUp(l); err != nil { + return nil, fmt.Errorf("failed to set link up: %v", err) + } // Set snaplen to 64KB to capture max size IP packets handle, err := pcap.OpenLive(kp.Kernel.GetDeviceName(), 65536, true, pcap.BlockForever) if err != nil { return nil, fmt.Errorf("failed to create afpacket: %v", err) } + if !kp.Kernel.GetAdminState() { + if err := netlink.LinkSetDown(l); err != nil { + return nil, fmt.Errorf("failed to set link down: %v", err) + } + } p := &kernelPort{ ctx: ctx, handle: handle, diff --git a/dataplane/forwarding/fwdport/ports/tap.go b/dataplane/forwarding/fwdport/ports/tap.go index 90876c59..f39fb211 100644 --- a/dataplane/forwarding/fwdport/ports/tap.go +++ b/dataplane/forwarding/fwdport/ports/tap.go @@ -280,6 +280,20 @@ func (tp tapBuilder) Build(portDesc *fwdpb.PortDesc, ctx *fwdcontext.Context) (f if err := unix.SetNonblock(fd, true); err != nil { return nil, fmt.Errorf("failed to set tap in non-blocking mode: %v", err) } + l, err := tp.ifaceMgr.LinkByName(kp.Tap.GetDeviceName()) + if err != nil { + return nil, fmt.Errorf("failed to get tap interface %q: %w", kp.Tap.GetDeviceName(), err) + } + isUp := l.Attrs().Flags&net.FlagUp != 0 + if kp.Tap.GetAdminState() && !isUp { + if err := tp.ifaceMgr.LinkSetUp(l); err != nil { + return nil, fmt.Errorf("failed to set tap interface %q up: %w", kp.Tap.GetDeviceName(), err) + } + } else if !kp.Tap.GetAdminState() && isUp { + if err := tp.ifaceMgr.LinkSetDown(l); err != nil { + return nil, fmt.Errorf("failed to set tap interface %q down: %w", kp.Tap.GetDeviceName(), err) + } + } file := os.NewFile(uintptr(fd), "/dev/tun") p := &tapPort{ ctx: ctx, diff --git a/dataplane/saiserver/ports.go b/dataplane/saiserver/ports.go index 7e8b344b..72406d1e 100644 --- a/dataplane/saiserver/ports.go +++ b/dataplane/saiserver/ports.go @@ -216,7 +216,7 @@ func (port *port) CreatePort(ctx context.Context, req *saipb.CreatePortRequest) SupportedFecMode: []saipb.PortFecMode{saipb.PortFecMode_PORT_FEC_MODE_NONE}, NumberOfIngressPriorityGroups: proto.Uint32(0), QosMaximumHeadroomSize: proto.Uint32(0), - AdminState: proto.Bool(true), + AdminState: proto.Bool(req.GetAdminState()), AutoNegMode: proto.Bool(req.GetAutoNegMode()), Mtu: proto.Uint32(1514), HwLaneList: req.HwLaneList, @@ -237,12 +237,11 @@ func (port *port) CreatePort(ctx context.Context, req *saipb.CreatePortRequest) fwdPort.Port.Port = &fwdpb.PortDesc_Kernel{ Kernel: &fwdpb.KernelPortDesc{ DeviceName: dev, + AdminState: req.GetAdminState(), }, } // For ports that don't exist, do not create dataplane ports. if _, err := getInterface(dev); err != nil { - attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_DOWN.Enum() - port.mgr.StoreAttributes(id, attrs) // TODO: This should be a real error, improve once we a correct config solution. // For now, create dummy port with no actions so we don't get a bunch error for a nonexistent port. fwdPort := &fwdpb.PortCreateRequest{ @@ -255,25 +254,16 @@ func (port *port) CreatePort(ctx context.Context, req *saipb.CreatePortRequest) Port: &fwdpb.PortDesc_Tap{ Tap: &fwdpb.TAPPortDesc{ DeviceName: fmt.Sprintf("port%d", id), + AdminState: req.GetAdminState(), }, }, }, } - _, err := port.dataplane.PortCreate(ctx, fwdPort) - if err != nil { - return nil, err - } - stateReq := &fwdpb.PortStateRequest{ - ContextId: &fwdpb.ContextId{Id: port.dataplane.ID()}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(id)}}, - Operation: &fwdpb.PortInfo{ - AdminStatus: fwdpb.PortState_PORT_STATE_DISABLED_DOWN, - }, - } - if _, err := port.dataplane.PortState(ctx, stateReq); err != nil { + if _, err := port.dataplane.PortCreate(ctx, fwdPort); err != nil { return nil, err } - + attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_DOWN.Enum() + port.mgr.StoreAttributes(id, attrs) return &saipb.CreatePortResponse{ Oid: id, }, nil @@ -310,23 +300,11 @@ func (port *port) CreatePort(ctx context.Context, req *saipb.CreatePortRequest) if _, err := port.dataplane.PortUpdate(ctx, update); err != nil { return nil, err } - attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_UP.Enum() - if req.AdminState == nil || req.GetAdminState() == false { - stateReq := &fwdpb.PortStateRequest{ - ContextId: &fwdpb.ContextId{Id: port.dataplane.ID()}, - PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(id)}}, - Operation: &fwdpb.PortInfo{ - AdminStatus: fwdpb.PortState_PORT_STATE_DISABLED_DOWN, - }, - } - _, err := port.dataplane.PortState(ctx, stateReq) - if err != nil { - return nil, err - } - attrs.AdminState = proto.Bool(false) + if req.GetAdminState() { + attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_UP.Enum() + } else { attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_DOWN.Enum() } - port.mgr.StoreAttributes(id, attrs) // Update the switch's port list. diff --git a/dataplane/saiserver/ports_test.go b/dataplane/saiserver/ports_test.go index 8f1ca2fa..9f1a7399 100644 --- a/dataplane/saiserver/ports_test.go +++ b/dataplane/saiserver/ports_test.go @@ -102,7 +102,7 @@ func TestCreatePort(t *testing.T) { SupportedFecMode: []saipb.PortFecMode{saipb.PortFecMode_PORT_FEC_MODE_NONE}, NumberOfIngressPriorityGroups: proto.Uint32(0), QosMaximumHeadroomSize: proto.Uint32(0), - AdminState: proto.Bool(true), + AdminState: proto.Bool(false), AutoNegMode: proto.Bool(false), Mtu: proto.Uint32(1514), PortVlanId: proto.Uint32(DefaultVlanId), diff --git a/proto/forwarding/forwarding_port.pb.go b/proto/forwarding/forwarding_port.pb.go index 72cc42f4..690514f0 100644 --- a/proto/forwarding/forwarding_port.pb.go +++ b/proto/forwarding/forwarding_port.pb.go @@ -450,6 +450,7 @@ func (x *CPUPortDesc) GetRemotePort() bool { type KernelPortDesc struct { state protoimpl.MessageState `protogen:"open.v1"` DeviceName string `protobuf:"bytes,1,opt,name=device_name,json=deviceName,proto3" json:"device_name,omitempty"` + AdminState bool `protobuf:"varint,2,opt,name=admin_state,json=adminState,proto3" json:"admin_state,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -491,9 +492,17 @@ func (x *KernelPortDesc) GetDeviceName() string { return "" } +func (x *KernelPortDesc) GetAdminState() bool { + if x != nil { + return x.AdminState + } + return false +} + type TAPPortDesc struct { state protoimpl.MessageState `protogen:"open.v1"` DeviceName string `protobuf:"bytes,1,opt,name=device_name,json=deviceName,proto3" json:"device_name,omitempty"` + AdminState bool `protobuf:"varint,2,opt,name=admin_state,json=adminState,proto3" json:"admin_state,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -535,6 +544,13 @@ func (x *TAPPortDesc) GetDeviceName() string { return "" } +func (x *TAPPortDesc) GetAdminState() bool { + if x != nil { + return x.AdminState + } + return false +} + type FakePortDesc struct { state protoimpl.MessageState `protogen:"open.v1"` InFile string `protobuf:"bytes,1,opt,name=in_file,json=inFile,proto3" json:"in_file,omitempty"` @@ -1669,13 +1685,17 @@ const file_proto_forwarding_forwarding_port_proto_rawDesc = "" + "\fqueue_length\x18\x02 \x01(\x05R\vqueueLength\x12C\n" + "\x10export_field_ids\x18\x03 \x03(\v2\x19.forwarding.PacketFieldIdR\x0eexportFieldIds\x12\x1f\n" + "\vremote_port\x18\x04 \x01(\bR\n" + - "remotePort\"1\n" + + "remotePort\"R\n" + "\x0eKernelPortDesc\x12\x1f\n" + "\vdevice_name\x18\x01 \x01(\tR\n" + - "deviceName\".\n" + + "deviceName\x12\x1f\n" + + "\vadmin_state\x18\x02 \x01(\bR\n" + + "adminState\"O\n" + "\vTAPPortDesc\x12\x1f\n" + "\vdevice_name\x18\x01 \x01(\tR\n" + - "deviceName\"[\n" + + "deviceName\x12\x1f\n" + + "\vadmin_state\x18\x02 \x01(\bR\n" + + "adminState\"[\n" + "\fFakePortDesc\x12\x17\n" + "\ain_file\x18\x01 \x01(\tR\x06inFile\x12\x19\n" + "\bout_file\x18\x02 \x01(\tR\aoutFile\x12\x17\n" + diff --git a/proto/forwarding/forwarding_port.proto b/proto/forwarding/forwarding_port.proto index 74cbcf0f..60983524 100644 --- a/proto/forwarding/forwarding_port.proto +++ b/proto/forwarding/forwarding_port.proto @@ -62,10 +62,12 @@ message CPUPortDesc { message KernelPortDesc { string device_name = 1; + bool admin_state = 2; } message TAPPortDesc { string device_name = 1; + bool admin_state = 2; } message FakePortDesc {