Skip to content

Commit

Permalink
Merge branch 'main' into acl
Browse files Browse the repository at this point in the history
  • Loading branch information
guoshiuan authored Jul 19, 2024
2 parents 2812208 + e9369ce commit 83b0dba
Show file tree
Hide file tree
Showing 9 changed files with 341 additions and 101 deletions.
4 changes: 4 additions & 0 deletions dataplane/forwarding/protocol/attr.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ var FieldAttr = map[fwdpb.PacketFieldNum]struct {
},
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID: {
Sizes: []int{SizeUint64},
},
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID: {
Sizes: []int{SizeUint64},
},
}

Expand Down Expand Up @@ -233,6 +236,7 @@ var GroupAttr = map[fwdpb.PacketHeaderGroup]struct {
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_HOST_PORT_ID,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID,
},
},
fwdpb.PacketHeaderGroup_PACKET_HEADER_GROUP_L2: {
Expand Down
15 changes: 11 additions & 4 deletions dataplane/forwarding/protocol/metadata/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ type Metadata struct {
outputIface []byte // L3 output interface id.
tunnelID []byte // Tunnel ID
hostPortID []byte // Host port id
l2mcgid []byte // L2MC Group ID
l2mcGroupID []byte // L2MC Group ID
policer []byte // Policer ID
desc *protocol.Desc // Protocol descriptor.
}

Expand Down Expand Up @@ -128,7 +129,9 @@ func (m *Metadata) Field(id fwdpacket.FieldID) ([]byte, error) {
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_HOST_PORT_ID:
return m.hostPortID, nil
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID:
return m.l2mcgid, nil
return m.l2mcGroupID, nil
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID:
return m.policer, nil

default:
return nil, fmt.Errorf("metadata: Field %v failed, unsupported field", id)
Expand Down Expand Up @@ -236,7 +239,10 @@ func (m *Metadata) updateSet(id fwdpacket.FieldID, arg []byte) (bool, error) {
m.hostPortID = arg
return true, nil
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID:
m.l2mcgid = arg
m.l2mcGroupID = arg
return true, nil
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID:
m.policer = arg
return true, nil
default:
return false, fmt.Errorf("metadata: UpdateField failed, set unsupported for field %v", id)
Expand Down Expand Up @@ -293,7 +299,8 @@ func parse(frame *frame.Frame, desc *protocol.Desc) (protocol.Handler, fwdpb.Pac
outputIface: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_OUTPUT_IFACE].DefaultSize),
tunnelID: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_TUNNEL_ID].DefaultSize),
hostPortID: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_HOST_PORT_ID].DefaultSize),
l2mcgid: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID].DefaultSize),
l2mcGroupID: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L2MC_GROUP_ID].DefaultSize),
policer: make([]byte, protocol.FieldAttr[fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID].DefaultSize),
attribute32: make(map[uint8][]byte),
attribute24: make(map[uint8][]byte),
attribute16: make(map[uint8][]byte),
Expand Down
1 change: 1 addition & 0 deletions dataplane/saiserver/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ go_test(
"acl_test.go",
"hostif_test.go",
"l2mc_test.go",
"policer_test.go",
"ports_test.go",
"routing_test.go",
"switch_test.go",
Expand Down
6 changes: 6 additions & 0 deletions dataplane/saiserver/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,12 @@ func (a *acl) CreateAclEntry(ctx context.Context, req *saipb.CreateAclEntryReque
default:
return nil, status.Errorf(codes.InvalidArgument, "type %q is not supported; only support L2MC Group for ACL Redirect for now", typ.String())
}
if req.ActionSetPolicer != nil {
aReq.Actions = append(aReq.Actions,
fwdconfig.Action(fwdconfig.UpdateAction(fwdpb.UpdateType_UPDATE_TYPE_SET, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID).
WithUint64Value(req.GetActionSetPolicer().GetOid())).Build(),
fwdconfig.Action(fwdconfig.LookupAction(policerTabler)).Build(),
)
}

cpuPortReq := &saipb.GetSwitchAttributeRequest{Oid: switchID, AttrType: []saipb.SwitchAttr{saipb.SwitchAttr_SWITCH_ATTR_CPU_PORT}}
Expand Down
41 changes: 37 additions & 4 deletions dataplane/saiserver/policer.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ package saiserver

import (
"context"
"fmt"

"google.golang.org/grpc"

"github.com/openconfig/lemming/dataplane/forwarding/fwdconfig"
"github.com/openconfig/lemming/dataplane/saiserver/attrmgr"

saipb "github.com/openconfig/lemming/dataplane/proto/sai"
fwdpb "github.com/openconfig/lemming/proto/forwarding"
)

type policer struct {
Expand All @@ -39,16 +42,46 @@ func newPolicer(mgr *attrmgr.AttrMgr, dataplane switchDataplaneAPI, s *grpc.Serv
return p
}

// CreatePolicer return policer.
func (p *policer) CreatePolicer(context.Context, *saipb.CreatePolicerRequest) (*saipb.CreatePolicerResponse, error) {
// CreatePolicer creates a new policer, QOS is not actually supported.ß the GREEN action is always taken.
func (p *policer) CreatePolicer(ctx context.Context, req *saipb.CreatePolicerRequest) (*saipb.CreatePolicerResponse, error) {
id := p.mgr.NextID()
// TODO: provide implementation.

cpuPortReq := &saipb.GetSwitchAttributeRequest{Oid: switchID, AttrType: []saipb.SwitchAttr{saipb.SwitchAttr_SWITCH_ATTR_CPU_PORT}}
resp := &saipb.GetSwitchAttributeResponse{}
if err := p.mgr.PopulateAttributes(cpuPortReq, resp); err != nil {
return nil, err
}

var action *fwdconfig.ActionBuilder

switch req.GetGreenPacketAction() {
case saipb.PacketAction_PACKET_ACTION_TRAP:
action = fwdconfig.Action(fwdconfig.TransmitAction(fmt.Sprint(resp.GetAttr().GetCpuPort())).WithImmediate(true))
default:
return nil, fmt.Errorf("unsupport policer action: %v", req.GetGreenPacketAction())
}

tReq := fwdconfig.TableEntryAddRequest(p.dataplane.ID(), policerTabler).
AppendEntry(fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID).WithUint64(id))), action)

if _, err := p.dataplane.TableEntryAdd(ctx, tReq.Build()); err != nil {
return nil, err
}

return &saipb.CreatePolicerResponse{
Oid: id,
}, nil
}

func (p *policer) RemovePolicer(context.Context, *saipb.RemovePolicerRequest) (*saipb.RemovePolicerResponse, error) {
// RemovePolicer removes the entry from the table.
func (p *policer) RemovePolicer(ctx context.Context, req *saipb.RemovePolicerRequest) (*saipb.RemovePolicerResponse, error) {
tReq := fwdconfig.TableEntryRemoveRequest(p.dataplane.ID(), policerTabler).
AppendEntry(fwdconfig.EntryDesc(fwdconfig.ExactEntry(fwdconfig.PacketFieldBytes(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID).WithUint64(req.GetOid()))))

if _, err := p.dataplane.TableEntryRemove(ctx, tReq.Build()); err != nil {
return nil, err
}

return &saipb.RemovePolicerResponse{}, nil
}

Expand Down
162 changes: 162 additions & 0 deletions dataplane/saiserver/policer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package saiserver

import (
"context"
"encoding/binary"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/openconfig/gnmi/errdiff"
"google.golang.org/grpc"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"

saipb "github.com/openconfig/lemming/dataplane/proto/sai"
"github.com/openconfig/lemming/dataplane/saiserver/attrmgr"
fwdpb "github.com/openconfig/lemming/proto/forwarding"
)

func TestCreatePolicer(t *testing.T) {
tests := []struct {
desc string
req *saipb.CreatePolicerRequest
wantErr string
want *fwdpb.TableEntryAddRequest
}{{
desc: "trap action",
req: &saipb.CreatePolicerRequest{
GreenPacketAction: saipb.PacketAction_PACKET_ACTION_TRAP.Enum(),
},
want: &fwdpb.TableEntryAddRequest{
ContextId: &fwdpb.ContextId{Id: "foo"},
TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: policerTabler}},
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_POLICER_ID},
},
Bytes: binary.BigEndian.AppendUint64(nil, 2),
}},
},
},
},
Actions: []*fwdpb.ActionDesc{{
ActionType: fwdpb.ActionType_ACTION_TYPE_TRANSMIT,
Action: &fwdpb.ActionDesc_Transmit{
Transmit: &fwdpb.TransmitActionDesc{
PortId: &fwdpb.PortId{ObjectId: &fwdpb.ObjectId{Id: "10"}},
Immediate: true,
},
},
}},
}},
},
}}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
dplane := &fakeSwitchDataplane{}
c, p, stopFn := newTestPolicer(t, dplane)
p.mgr.StoreAttributes(p.mgr.NextID(), &saipb.SwitchAttribute{
CpuPort: proto.Uint64(10),
})
defer stopFn()
_, gotErr := c.CreatePolicer(context.TODO(), tt.req)
if diff := errdiff.Check(gotErr, tt.wantErr); diff != "" {
t.Fatalf("CreatePolicer() unexpected err: %s", diff)
}
if gotErr != nil {
return
}
if d := cmp.Diff(dplane.gotEntryAddReqs[0], tt.want, protocmp.Transform()); d != "" {
t.Errorf("CreatePolicer() failed: diff(-got,+want)\n:%s", d)
}
})
}
}

func TestRemovePolicer(t *testing.T) {
tests := []struct {
desc string
req *saipb.RemovePolicerRequest
wantErr string
want *fwdpb.TableEntryRemoveRequest
}{{
desc: "not found",
req: &saipb.RemovePolicerRequest{
Oid: 3,
},
wantErr: "not found",
}, {
desc: "success",
req: &saipb.RemovePolicerRequest{
Oid: 2,
},
want: &fwdpb.TableEntryRemoveRequest{
ContextId: &fwdpb.ContextId{Id: "foo"},
TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: policerTabler}},
Entries: []*fwdpb.EntryDesc{{
Entry: &fwdpb.EntryDesc_Exact{
Exact: &fwdpb.ExactEntryDesc{
Fields: []*fwdpb.PacketFieldBytes{{
FieldId: &fwdpb.PacketFieldId{
Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID},
},
Bytes: binary.BigEndian.AppendUint64(nil, 2),
}},
},
},
}},
},
}}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
dplane := &fakeSwitchDataplane{}
c, a, stopFn := newTestPolicer(t, dplane)
a.mgr.StoreAttributes(a.mgr.NextID(), &saipb.SwitchAttribute{
CpuPort: proto.Uint64(10),
})
defer stopFn()
_, err := c.CreatePolicer(context.TODO(), &saipb.CreatePolicerRequest{
GreenPacketAction: saipb.PacketAction_PACKET_ACTION_TRAP.Enum(),
})
if err != nil {
t.Fatal(err)
}
_, gotErr := c.RemovePolicer(context.Background(), tt.req)
if diff := errdiff.Check(gotErr, tt.wantErr); diff != "" {
t.Fatalf("RemovePolicer() unexpected err: %s", diff)
}
if gotErr != nil {
return
}
if d := cmp.Diff(dplane.gotEntryRemoveReqs[0], tt.want, protocmp.Transform()); d != "" {
t.Errorf("RemovePolicer() failed: diff(-got,+want)\n:%s", d)
}
})
}
}

func newTestPolicer(t testing.TB, api switchDataplaneAPI) (saipb.PolicerClient, *policer, func()) {
var p *policer
conn, _, stopFn := newTestServer(t, func(mgr *attrmgr.AttrMgr, srv *grpc.Server) {
p = newPolicer(mgr, api, srv)
})
return saipb.NewPolicerClient(conn), p, stopFn
}
21 changes: 21 additions & 0 deletions dataplane/saiserver/switch.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ const (
tunTermTable = "tun-term"
VlanTable = "vlan"
L2MCGroupTable = "l2mcg"
policerTabler = "policerTable"
DefaultVlanId = 1
)

Expand Down Expand Up @@ -624,6 +625,26 @@ func (sw *saiSwitch) CreateSwitch(ctx context.Context, _ *saipb.CreateSwitchRequ
return nil, err
}

_, err = sw.dataplane.TableCreate(ctx, &fwdpb.TableCreateRequest{
ContextId: &fwdpb.ContextId{Id: sw.dataplane.ID()},
Desc: &fwdpb.TableDesc{
TableId: &fwdpb.TableId{ObjectId: &fwdpb.ObjectId{Id: policerTabler}},
TableType: fwdpb.TableType_TABLE_TYPE_EXACT,
Table: &fwdpb.TableDesc_Exact{
Exact: &fwdpb.ExactTableDesc{
FieldIds: []*fwdpb.PacketFieldId{{
Field: &fwdpb.PacketField{
FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_POLICER_ID,
},
}},
},
},
},
})
if err != nil {
return nil, err
}

cpuPortID, err := sw.port.createCPUPort(ctx)
if err != nil {
return nil, err
Expand Down
Loading

0 comments on commit 83b0dba

Please sign in to comment.