diff --git a/dataplane/saiserver/routing.go b/dataplane/saiserver/routing.go index 38887577..0ad054f5 100644 --- a/dataplane/saiserver/routing.go +++ b/dataplane/saiserver/routing.go @@ -532,6 +532,12 @@ func (nh *nextHop) CreateNextHop(ctx context.Context, req *saipb.CreateNextHopRe }, }) case saipb.TunnelType_TUNNEL_TYPE_VXLAN: + if len(req.GetTunnelMac()) > 0 { + actions = append(actions, + fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_SRC).WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST)).Build(), + fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST).WithValue(req.GetTunnelMac())).Build(), + ) + } actions = append(actions, &fwdpb.ActionDesc{ ActionType: fwdpb.ActionType_ACTION_TYPE_ENCAP, Action: &fwdpb.ActionDesc_Encap{ @@ -554,6 +560,11 @@ func (nh *nextHop) CreateNextHop(ctx context.Context, req *saipb.CreateNextHopRe }, }, }) + if req.GetTunnelVni() != 0 { + vni := req.GetTunnelVni() + vniBytes := []byte{byte(vni >> 16), byte(vni >> 8), byte(vni)} + actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_VXLAN_VNI).WithValue(vniBytes)).Build()) + } default: return nil, status.Errorf(codes.InvalidArgument, "unsupported tunnel type: %v", tunnel.GetAttr().GetType()) } @@ -562,18 +573,6 @@ func (nh *nextHop) CreateNextHop(ctx context.Context, req *saipb.CreateNextHopRe fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST).WithValue(req.GetIp())).Build(), fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP).WithValue(req.GetIp())).Build(), fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID).WithUint64Value(req.GetTunnelId())).Build(), - ) - - if req.GetTunnelVni() != 0 { - vni := req.GetTunnelVni() - vniBytes := []byte{byte(vni >> 16), byte(vni >> 8), byte(vni)} - actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_VXLAN_VNI).WithValue(vniBytes)).Build()) - } - if len(req.GetTunnelMac()) > 0 { - actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST).WithValue(req.GetTunnelMac())).Build()) - } - - actions = append(actions, fwdconfig.Action(fwdconfig.LookupAction(NHActionTable)).Build(), fwdconfig.Action(fwdconfig.LookupAction(TunnelEncap)).Build(), ) diff --git a/dataplane/saiserver/routing_test.go b/dataplane/saiserver/routing_test.go index 1d8ff364..b14f6385 100644 --- a/dataplane/saiserver/routing_test.go +++ b/dataplane/saiserver/routing_test.go @@ -678,6 +678,37 @@ func TestCreateNextHop(t *testing.T) { TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: NHTable}}, Entries: []*fwdpb.TableEntryAddRequest_Entry{{ Actions: []*fwdpb.ActionDesc{{ + ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, + Action: &fwdpb.ActionDesc_Update{ + Update: &fwdpb.UpdateActionDesc{ + Type: fwdpb.UpdateType_UPDATE_TYPE_COPY, + FieldId: &fwdpb.PacketFieldId{ + Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_SRC, + }, + }, + Field: &fwdpb.PacketFieldId{ + Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, + }, + }, + }, + }, + }, { + ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, + Action: &fwdpb.ActionDesc_Update{ + Update: &fwdpb.UpdateActionDesc{ + Type: fwdpb.UpdateType_UPDATE_TYPE_SET, + FieldId: &fwdpb.PacketFieldId{ + Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, + }, + }, + Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, + Value: []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + }, + }, + }, { ActionType: fwdpb.ActionType_ACTION_TYPE_ENCAP, Action: &fwdpb.ActionDesc_Encap{ Encap: &fwdpb.EncapActionDesc{ @@ -705,11 +736,11 @@ func TestCreateNextHop(t *testing.T) { Type: fwdpb.UpdateType_UPDATE_TYPE_SET, FieldId: &fwdpb.PacketFieldId{ Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_VXLAN_VNI, }, }, Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, - Value: []byte{0x7f, 0x00, 0x00, 0x01}, + Value: []byte{0x12, 0x34, 0x56}, }, }, }, { @@ -719,7 +750,7 @@ func TestCreateNextHop(t *testing.T) { Type: fwdpb.UpdateType_UPDATE_TYPE_SET, FieldId: &fwdpb.PacketFieldId{ Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP, + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, }, }, Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, @@ -733,25 +764,11 @@ func TestCreateNextHop(t *testing.T) { Type: fwdpb.UpdateType_UPDATE_TYPE_SET, FieldId: &fwdpb.PacketFieldId{ Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID, - }, - }, - Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, - Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, - }, - }, - }, { - ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, - Action: &fwdpb.ActionDesc_Update{ - Update: &fwdpb.UpdateActionDesc{ - Type: fwdpb.UpdateType_UPDATE_TYPE_SET, - FieldId: &fwdpb.PacketFieldId{ - Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_VXLAN_VNI, + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_IP, }, }, Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, - Value: []byte{0x12, 0x34, 0x56}, + Value: []byte{0x7f, 0x00, 0x00, 0x01}, }, }, }, { @@ -761,11 +778,11 @@ func TestCreateNextHop(t *testing.T) { Type: fwdpb.UpdateType_UPDATE_TYPE_SET, FieldId: &fwdpb.PacketFieldId{ Field: &fwdpb.PacketField{ - FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST, + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID, }, }, Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{}}, - Value: []byte{0x00, 0x11, 0x22, 0x33, 0x44, 0x55}, + Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f}, }, }, }, { diff --git a/dataplane/saiserver/tunnel.go b/dataplane/saiserver/tunnel.go index abe5dc32..923b3b1b 100644 --- a/dataplane/saiserver/tunnel.go +++ b/dataplane/saiserver/tunnel.go @@ -30,6 +30,8 @@ import ( fwdpb "github.com/openconfig/lemming/proto/forwarding" ) +const defaultEncapTTL = 255 // Default of SAI_TUNNEL_ATTR_ENCAP_TTL_VAL. + type tunnel struct { saipb.UnimplementedTunnelServer mgr *attrmgr.AttrMgr @@ -68,9 +70,18 @@ func (t *tunnel) CreateTunnel(ctx context.Context, req *saipb.CreateTunnelReques } ttlMode := req.GetEncapTtlMode() - if ttlMode == saipb.TunnelTtlMode_TUNNEL_TTL_MODE_UNIFORM_MODEL { // Copy the TTL from the inner IP header. + switch ttlMode { + case saipb.TunnelTtlMode_TUNNEL_TTL_MODE_UNSPECIFIED, saipb.TunnelTtlMode_TUNNEL_TTL_MODE_UNIFORM_MODEL: + // Copy the TTL from the inner IP header. actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_COPY, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP). WithFieldSrc(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP).WithFieldSrcInstance(1)).Build()) + case saipb.TunnelTtlMode_TUNNEL_TTL_MODE_PIPE_MODEL: + ttl := uint8(defaultEncapTTL) + if req.EncapTtlVal != nil { + ttl = uint8(req.GetEncapTtlVal()) + } + actions = append(actions, fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP). + WithValue([]byte{ttl})).Build()) } if req.GetEncapSrcIp() != nil { diff --git a/dataplane/saiserver/tunnel_test.go b/dataplane/saiserver/tunnel_test.go index 8cb138a7..185e75fa 100644 --- a/dataplane/saiserver/tunnel_test.go +++ b/dataplane/saiserver/tunnel_test.go @@ -135,6 +135,18 @@ func TestCreateTunnel(t *testing.T) { Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, }, }, + }, { + ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, + Action: &fwdpb.ActionDesc_Update{ + Update: &fwdpb.UpdateActionDesc{ + Type: fwdpb.UpdateType_UPDATE_TYPE_COPY, + Field: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{ + FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP, + Instance: 1, + }}, + FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP}}, + }, + }, }, { ActionType: fwdpb.ActionType_ACTION_TYPE_UPDATE, Action: &fwdpb.ActionDesc_Update{ @@ -158,6 +170,119 @@ func TestCreateTunnel(t *testing.T) { }}, }}, }, + }, { + desc: "vxlan tunnel pipe ttl", + req: &saipb.CreateTunnelRequest{ + Type: saipb.TunnelType_TUNNEL_TYPE_VXLAN.Enum(), + EncapTtlMode: saipb.TunnelTtlMode_TUNNEL_TTL_MODE_PIPE_MODEL.Enum(), + EncapTtlVal: proto.Uint32(32), + UnderlayInterface: proto.Uint64(10), + }, + wantReq: &fwdpb.TableEntryAddRequest{ + ContextId: &fwdpb.ContextId{Id: "foo"}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: TunnelEncap}}, + Entries: []*fwdpb.TableEntryAddRequest_Entry{{ + EntryDesc: &fwdpb.EntryDesc{ + Entry: &fwdpb.EntryDesc_Exact{ + Exact: &fwdpb.ExactEntryDesc{ + Fields: []*fwdpb.PacketFieldBytes{{ + FieldId: &fwdpb.PacketFieldId{ + Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID}, + }, + Bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + }}, + }, + }, + }, + Actions: []*fwdpb.ActionDesc{{ + 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_OUTPUT_IFACE}}, + Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, + }, + }, + }, { + 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_IP_HOP}}, + Value: []byte{32}, + }, + }, + }, { + 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_L4_PORT_DST}}, + Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb5}, + }, + }, + }}, + }}, + }, + }, { + desc: "vxlan tunnel pipe default ttl", + req: &saipb.CreateTunnelRequest{ + Type: saipb.TunnelType_TUNNEL_TYPE_VXLAN.Enum(), + EncapTtlMode: saipb.TunnelTtlMode_TUNNEL_TTL_MODE_PIPE_MODEL.Enum(), + UnderlayInterface: proto.Uint64(10), + }, + wantReq: &fwdpb.TableEntryAddRequest{ + ContextId: &fwdpb.ContextId{Id: "foo"}, + TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: TunnelEncap}}, + Entries: []*fwdpb.TableEntryAddRequest_Entry{{ + EntryDesc: &fwdpb.EntryDesc{ + Entry: &fwdpb.EntryDesc_Exact{ + Exact: &fwdpb.ExactEntryDesc{ + Fields: []*fwdpb.PacketFieldBytes{{ + FieldId: &fwdpb.PacketFieldId{ + Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID}, + }, + Bytes: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, + }}, + }, + }, + }, + Actions: []*fwdpb.ActionDesc{{ + 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_OUTPUT_IFACE}}, + Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a}, + }, + }, + }, { + 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_IP_HOP}}, + Value: []byte{defaultEncapTTL}, + }, + }, + }, { + 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_L4_PORT_DST}}, + Value: []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xb5}, + }, + }, + }}, + }}, + }, }} for _, tt := range tests { t.Run(tt.desc, func(t *testing.T) {