Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions dataplane/saiserver/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ func (port *port) CreatePort(ctx context.Context, req *saipb.CreatePortRequest)
attrs.OperStatus = saipb.PortOperStatus_PORT_OPER_STATUS_NOT_PRESENT.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 nonexistant port.
// For now, create dummy port with no actions so we don't get a bunch error for a nonexistent port.
fwdPort := &fwdpb.PortCreateRequest{
ContextId: &fwdpb.ContextId{Id: port.dataplane.ID()},
Port: &fwdpb.PortDesc{
Expand Down Expand Up @@ -527,7 +527,7 @@ func (port *port) createCPUPort(ctx context.Context) (uint64, error) {
// SetPortAttributes sets the attributes in the request.
func (port *port) SetPortAttribute(ctx context.Context, req *saipb.SetPortAttributeRequest) (*saipb.SetPortAttributeResponse, error) {
if req.AdminState != nil {
// Skip ports that don't exsit.
// Skip ports that don't exist.
attrReq := &saipb.GetPortAttributeRequest{Oid: req.GetOid(), AttrType: []saipb.PortAttr{saipb.PortAttr_PORT_ATTR_OPER_STATUS}}
p := &saipb.GetPortAttributeResponse{}
if err := port.mgr.PopulateAttributes(attrReq, p); err != nil {
Expand All @@ -537,6 +537,33 @@ func (port *port) SetPortAttribute(ctx context.Context, req *saipb.SetPortAttrib
return nil, nil
}

// Do not apply admin-state changes to the fallback TAP created for a
// kernel-backed port whose real lane interface is absent.
if port.opts.PortType == fwdpb.PortType_PORT_TYPE_KERNEL && req.GetAdminState() {
attrReq := &saipb.GetPortAttributeRequest{
Oid: req.GetOid(),
AttrType: []saipb.PortAttr{saipb.PortAttr_PORT_ATTR_HW_LANE_LIST},
}
p := &saipb.GetPortAttributeResponse{}
if err := port.mgr.PopulateAttributes(attrReq, p); err != nil {
return nil, err
}
attr := p.GetAttr()
if attr == nil {
return nil, fmt.Errorf("failed to get attributes for port %d", req.GetOid())
}
lanes := attr.GetHwLaneList()
if len(lanes) == 0 {
return nil, fmt.Errorf("port %d has no hardware lanes", req.GetOid())
}
dev := fmt.Sprintf("eth%d", lanes[0])
if _, err := getInterface(dev); err != nil {
slog.InfoContext(ctx, "ignoring admin-state update for port without backing interface",
"oid", req.GetOid(), "device", dev, "admin_state", req.GetAdminState())
return &saipb.SetPortAttributeResponse{}, nil
}
}

stateReq := &fwdpb.PortStateRequest{
ContextId: &fwdpb.ContextId{Id: port.dataplane.ID()},
PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: fmt.Sprint(req.GetOid())}},
Expand Down Expand Up @@ -709,7 +736,7 @@ func (port *port) RemovePort(ctx context.Context, req *saipb.RemovePortRequest)
}

func (port *port) Reset() {
slog.Info("reseting port")
slog.Info("resetting port")
}

type lagMember struct {
Expand Down
35 changes: 35 additions & 0 deletions dataplane/saiserver/ports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,41 @@ func TestSetPortAttribute(t *testing.T) {
}
})
}

t.Run("admin status ignored without backing interface", func(t *testing.T) {
oldGetInterface := getInterface
defer func() { getInterface = oldGetInterface }()

getInterface = func(name string) (*net.Interface, error) {
if name != "eth125" {
t.Errorf("getInterface() got %q, want eth125", name)
}
return nil, fmt.Errorf("link not found")
}

dplane := &fakeSwitchDataplane{}
c, mgr, stopFn := newTestPort(t, dplane, &dplaneopts.Options{
PortType: fwdpb.PortType_PORT_TYPE_KERNEL,
})
defer stopFn()

mgr.StoreAttributes(3, &saipb.PortAttribute{
OperStatus: saipb.PortOperStatus_PORT_OPER_STATUS_DOWN.Enum(),
HwLaneList: []uint32{125, 126, 127, 128},
})

_, err := c.SetPortAttribute(context.Background(), &saipb.SetPortAttributeRequest{
Oid: 3,
AdminState: proto.Bool(true),
})
if err != nil {
t.Fatalf("SetPortAttribute() unexpected error: %v", err)
}
if got := len(dplane.gotPortStateReq); got != 0 {
t.Fatalf("SetPortAttribute() sent %d PortState requests, want 0", got)
}
})

fecTests := []struct {
desc string
req *saipb.SetPortAttributeRequest
Expand Down
Loading