From f63a2c1b98a678cdfa1ac3e1a527c52861b8defe Mon Sep 17 00:00:00 2001 From: Daniel Grau Date: Fri, 1 Nov 2024 16:54:06 -0700 Subject: [PATCH] Support route metadata (#493) * Support route metadata * feedback --- dataplane/saiserver/acl.go | 7 +++++++ dataplane/saiserver/acl_test.go | 8 ++++++++ dataplane/saiserver/ports.go | 8 ++++++++ dataplane/saiserver/routing.go | 20 +++++++++++++++----- dataplane/saiserver/routing_test.go | 14 ++++++++++++++ 5 files changed, 52 insertions(+), 5 deletions(-) diff --git a/dataplane/saiserver/acl.go b/dataplane/saiserver/acl.go index 65f51eef..016a660f 100644 --- a/dataplane/saiserver/acl.go +++ b/dataplane/saiserver/acl.go @@ -293,6 +293,13 @@ func (a *acl) createAclEntryFields(req *saipb.CreateAclEntryRequest, id uint64, Masks: []byte{byte(req.GetFieldTtl().GetMaskUint())}, }) } + if req.GetFieldRouteDstUserMeta() != nil { + aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{ + FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_ATTRIBUTE_32, Instance: routeDstMeta}}, + Bytes: binary.BigEndian.AppendUint32(nil, uint32(req.GetFieldRouteDstUserMeta().GetDataUint())), + Masks: binary.BigEndian.AppendUint32(nil, uint32(req.GetFieldRouteDstUserMeta().GetMaskUint())), + }) + } if len(req.GetUserDefinedFieldGroupMin()) > 0 { table := &saipb.AclTableAttribute{} if err := a.mgr.PopulateAllAttributes(fmt.Sprint(req.GetTableId()), table); err != nil { diff --git a/dataplane/saiserver/acl_test.go b/dataplane/saiserver/acl_test.go index 36858b94..1e8bd027 100644 --- a/dataplane/saiserver/acl_test.go +++ b/dataplane/saiserver/acl_test.go @@ -125,6 +125,10 @@ func TestCreateAclEntry(t *testing.T) { Data: &saipb.AclFieldData_DataUint{DataUint: 0x01}, Mask: &saipb.AclFieldData_MaskUint{MaskUint: 0xff}, }, + FieldRouteDstUserMeta: &saipb.AclFieldData{ + Data: &saipb.AclFieldData_DataUint{DataUint: 0x2}, + Mask: &saipb.AclFieldData_MaskUint{MaskUint: 0xff}, + }, }, want: &fwdpb.TableEntryAddRequest{ ContextId: &fwdpb.ContextId{Id: "foo"}, @@ -186,6 +190,10 @@ func TestCreateAclEntry(t *testing.T) { FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP}}, Bytes: []byte{0x01}, Masks: []byte{0xff}, + }, { + FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_ATTRIBUTE_32, Instance: routeDstMeta}}, + Bytes: []byte{0x0, 0x0, 0x0, 0x02}, + Masks: []byte{0x0, 0x0, 0x0, 0xff}, }}, }, }, diff --git a/dataplane/saiserver/ports.go b/dataplane/saiserver/ports.go index 7add81e8..bd6b562a 100644 --- a/dataplane/saiserver/ports.go +++ b/dataplane/saiserver/ports.go @@ -675,6 +675,14 @@ func (l *lag) RemoveLagMember(ctx context.Context, req *saipb.RemoveLagMemberReq return &saipb.RemoveLagMemberResponse{}, err } +func (l *lag) SetLagAttribute(context.Context, *saipb.SetLagAttributeRequest) (*saipb.SetLagAttributeResponse, error) { + return &saipb.SetLagAttributeResponse{}, nil +} + +func (l *lag) SetLagMemberAttribute(context.Context, *saipb.SetLagMemberAttributeRequest) (*saipb.SetLagMemberAttributeResponse, error) { + return &saipb.SetLagMemberAttributeResponse{}, nil +} + type queue struct { saipb.UnimplementedQueueServer mgr *attrmgr.AttrMgr diff --git a/dataplane/saiserver/routing.go b/dataplane/saiserver/routing.go index 6ad96048..51100f52 100644 --- a/dataplane/saiserver/routing.go +++ b/dataplane/saiserver/routing.go @@ -510,6 +510,9 @@ func newRoute(mgr *attrmgr.AttrMgr, dataplane switchDataplaneAPI, s *grpc.Server return r } +// routeDstMeta is the key to PACKET_ATTRIBUTE_32 field for routing table metadata. +const routeDstMeta = 0 + // CreateRouteEntry creates a new route entry. func (r *route) CreateRouteEntry(ctx context.Context, req *saipb.CreateRouteEntryRequest) (*saipb.CreateRouteEntryResponse, error) { fib := FIBV6Table @@ -535,21 +538,23 @@ func (r *route) CreateRouteEntry(ctx context.Context, req *saipb.CreateRouteEntr } nextType := r.mgr.GetType(fmt.Sprint(req.GetNextHopId())) + actions := []*fwdconfig.ActionBuilder{} + // If the packet action is drop, then next hop is optional. if forward { switch nextType { case saipb.ObjectType_OBJECT_TYPE_NEXT_HOP: - entry.AppendActions(fwdconfig.Action( + actions = append(actions, fwdconfig.Action( fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_ID).WithUint64Value(req.GetNextHopId())), fwdconfig.Action(fwdconfig.LookupAction(NHTable)), ) case saipb.ObjectType_OBJECT_TYPE_NEXT_HOP_GROUP: - entry.AppendActions(fwdconfig.Action( + actions = append(actions, fwdconfig.Action( fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID).WithUint64Value(req.GetNextHopId())), fwdconfig.Action(fwdconfig.LookupAction(NHGTable)), ) case saipb.ObjectType_OBJECT_TYPE_ROUTER_INTERFACE: - entry.AppendActions( + actions = append(actions, // Set the next hop IP in the packet's metadata. fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST)), // Set the output iface. @@ -579,7 +584,7 @@ func (r *route) CreateRouteEntry(ctx context.Context, req *saipb.CreateRouteEntr } return &saipb.CreateRouteEntryResponse{}, nil } - entry.AppendActions( + actions = append(actions, // Set the next hop IP in the packet's metadata. fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST)), // Set the output port. @@ -589,8 +594,13 @@ func (r *route) CreateRouteEntry(ctx context.Context, req *saipb.CreateRouteEntr return nil, status.Errorf(codes.InvalidArgument, "unknown next hop type: %v", nextType) } } else { - entry.AppendActions(fwdconfig.Action(fwdconfig.DropAction())) + actions = append(actions, fwdconfig.Action(fwdconfig.DropAction())) + } + if req.MetaData != nil { + actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_ATTRIBUTE_32). + WithFieldIDInstance(routeDstMeta).WithValue(binary.BigEndian.AppendUint32(nil, req.GetMetaData())))) } + entry.AppendActions(actions...) route := entry.Build() _, err := r.dataplane.TableEntryAdd(ctx, route) diff --git a/dataplane/saiserver/routing_test.go b/dataplane/saiserver/routing_test.go index cfc6dea1..1b170474 100644 --- a/dataplane/saiserver/routing_test.go +++ b/dataplane/saiserver/routing_test.go @@ -729,6 +729,7 @@ func TestCreateRouteEntry(t *testing.T) { SwitchId: 1, }, PacketAction: saipb.PacketAction_PACKET_ACTION_TRANSIT.Enum(), + MetaData: proto.Uint32(10), NextHopId: proto.Uint64(100), }, wantReq: &fwdpb.TableEntryAddRequest{ @@ -755,6 +756,19 @@ func TestCreateRouteEntry(t *testing.T) { PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: "100"}}, }, }, + }, { + ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, + Action: &fwdpb.ActionDesc_Update{ + Update: &fwdpb.UpdateActionDesc{ + Type: fwdpb.UpdateType_UPDATE_TYPE_SET, + Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, + FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_PACKET_ATTRIBUTE_32, + Instance: routeDstMeta, + }}, + Value: []uint8{0x00, 0x00, 0x00, 0x0a}, + }, + }, }}, EntryDesc: &fwdpb.EntryDesc{ Entry: &fwdpb.EntryDesc_Prefix{