Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for required ACL fields #306

Merged
merged 4 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 4 additions & 0 deletions dataplane/forwarding/protocol/attr.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ var FieldAttr = map[fwdpb.PacketFieldNum]struct {
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_NEXT_HOP_GROUP_ID: {
Sizes: []int{SizeUint64},
},
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP: {
Sizes: []int{SizeUint8},
},
}

// GroupAttr contains attributes for each packet header group.
Expand Down Expand Up @@ -246,6 +249,7 @@ var GroupAttr = map[fwdpb.PacketHeaderGroup]struct {
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP6_FLOW,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_GRE_KEY,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_GRE_SEQUENCE,
fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP,
},
},
fwdpb.PacketHeaderGroup_PACKET_HEADER_GROUP_L4: {
Expand Down
5 changes: 5 additions & 0 deletions dataplane/forwarding/protocol/ip/ip4.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const (
ip4DstBytes = ip4AddrBytes // Number of bytes in the dest IP address
ip4DstPos = 16 // Offset in bytes of the dest IP address
ip6to4Offset = 2 // Offset in bytes of the encoded ip4 address
dscpPos = 1 // Offset in bytes of the DSCP
dcspBits = 6 // Number of bits in the DSCP
)

// Constants defined for various 6to4 tunnels
Expand Down Expand Up @@ -89,6 +91,9 @@ func (ip *IP4) field(id fwdpacket.FieldID) frame.Field {

case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS:
return ip.header.Field(ip4TosPos, ip4TosBytes)
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP:
f := ip.header.Field(dscpPos, 1)
return f.BitField(0, 6)

case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_VERSION:
return ipVersion(ip.header)
Expand Down
4 changes: 3 additions & 1 deletion dataplane/forwarding/protocol/ip/ip6.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ func (ip *IP6) field(id fwdpacket.FieldID) frame.Field {

case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS, fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP6_FLOW:
return ip.header.Field(ip6DescPos, ip6DescBytes)

case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP:
f := ip.header.Field(dscpPos, 1)
return f.BitField(0, 6)
case fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_VERSION:
return ipVersion(ip.header)

Expand Down
87 changes: 39 additions & 48 deletions dataplane/forwarding/protocol/packet/ip4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,55 +31,46 @@ import (
var ip4 = []byte{0x45, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x08, 0xff, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d, 0x00, 0x00}
DanG100 marked this conversation as resolved.
Show resolved Hide resolved

func TestIP4(t *testing.T) {
queries := []packettestutil.FieldQuery{
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_VERSION, 0),
Result: []byte{0x04},
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_SRC, 0),
Result: []byte{0x01, 0x02, 0x03, 0x04},
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, 0),
Result: []byte{0x0a, 0x0b, 0x0c, 0x0d},
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS, 0),
Result: []byte{0x01},
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP, 0),
Result: []byte{0x08},
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_PROTO, 0),
Result: []byte{0xff},
},
}
queries := []packettestutil.FieldQuery{{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_VERSION, 0),
Result: []byte{0x04},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_SRC, 0),
Result: []byte{0x01, 0x02, 0x03, 0x04},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, 0),
Result: []byte{0x0a, 0x0b, 0x0c, 0x0d},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS, 0),
Result: []byte{0x01},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP, 0),
Result: []byte{0x08},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_PROTO, 0),
Result: []byte{0xff},
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP, 0),
Result: []byte{0x01},
}}

updates := []packettestutil.FieldUpdate{
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_SRC, 0),
Arg: []byte{0x11, 0x12, 0x13, 0x14},
Op: fwdpacket.OpSet,
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, 0),
Arg: []byte{0x1a, 0x1b, 0x1c, 0x1d},
Op: fwdpacket.OpSet,
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS, 0),
Arg: []byte{0x0d},
Op: fwdpacket.OpSet,
},
{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP, 0),
Arg: []byte{0x01},
Op: fwdpacket.OpDec,
},
}
updates := []packettestutil.FieldUpdate{{
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_SRC, 0),
Arg: []byte{0x11, 0x12, 0x13, 0x14},
Op: fwdpacket.OpSet,
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST, 0),
Arg: []byte{0x1a, 0x1b, 0x1c, 0x1d},
Op: fwdpacket.OpSet,
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_QOS, 0),
Arg: []byte{0x0d},
Op: fwdpacket.OpSet,
}, {
ID: fwdpacket.NewFieldIDFromNum(fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP, 0),
Arg: []byte{0x01},
Op: fwdpacket.OpDec,
}}

ipFinal := []byte{0x45, 0x0d, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x58, 0x7f, 0x11, 0x12, 0x13, 0x14, 0x1a, 0x1b, 0x1c, 0x1d, 0x00, 0x00}

Expand Down
1 change: 1 addition & 0 deletions dataplane/standalone/saiserver/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ go_library(
go_test(
name = "saiserver_test",
srcs = [
"acl_test.go",
"ports_test.go",
"routing_test.go",
"switch_test.go",
Expand Down
99 changes: 96 additions & 3 deletions dataplane/standalone/saiserver/acl.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,14 @@ func (a *acl) CreateAclEntry(ctx context.Context, req *saipb.CreateAclEntryReque
},
},
}
switch {
case req.GetFieldDstIp() != nil:
if req.GetFieldDstIp() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST}},
Bytes: req.GetFieldDstIp().GetDataIp(),
Masks: req.GetFieldDstIp().GetMaskIp(),
})
case req.GetFieldInPort() != nil:
}
if req.GetFieldInPort() != nil {
nid, ok := a.dataplane.PortIDToNID(fmt.Sprint(req.FieldInPort.GetDataOid()))
if !ok {
return nil, fmt.Errorf("unknown port with id: %v", req.FieldInPort.GetDataOid())
Expand All @@ -169,6 +169,99 @@ func (a *acl) CreateAclEntry(ctx context.Context, req *saipb.CreateAclEntryReque
Masks: binary.BigEndian.AppendUint64(nil, math.MaxUint64),
})
}
if req.GetFieldAclIpType() != nil {
fieldMask := &fwdpb.PacketFieldMaskedBytes{
DanG100 marked this conversation as resolved.
Show resolved Hide resolved
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_TYPE}},
Bytes: binary.BigEndian.AppendUint16(nil, 0x0000),
Masks: binary.BigEndian.AppendUint16(nil, 0xFFFF),
}
switch t := req.GetFieldAclIpType().GetDataIpType(); t {
case saipb.AclIpType_ACL_IP_TYPE_ANY:
fieldMask.Masks = binary.BigEndian.AppendUint16(nil, 0x0000)
case saipb.AclIpType_ACL_IP_TYPE_IPV4ANY:
fieldMask.Bytes = binary.BigEndian.AppendUint16(nil, 0x0800)
case saipb.AclIpType_ACL_IP_TYPE_IPV6ANY:
fieldMask.Bytes = binary.BigEndian.AppendUint16(nil, 0x86DD)
case saipb.AclIpType_ACL_IP_TYPE_ARP:
fieldMask.Bytes = binary.BigEndian.AppendUint16(nil, 0x0806)
default:
return nil, status.Errorf(codes.InvalidArgument, "unspporrted ACL_IP_TYPE: %v", t)
}
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, fieldMask)
}
if req.GetFieldDscp() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_DSCP}},
Bytes: []byte{byte(req.GetFieldDscp().GetDataUint())},
Masks: []byte{byte(req.GetFieldDscp().GetMaskUint())},
})
}
if req.GetFieldDstIpv6Word3() != nil { // Word3 is supposed to match the 127:96 bits of the IP, assume the caller is masking this correctly put the whole IP in the table.
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST}},
Bytes: req.GetFieldDstIpv6Word3().GetDataIp(),
Masks: req.GetFieldDstIpv6Word3().GetMaskIp(),
})
}
if req.GetFieldDstIpv6Word2() != nil { // Word2 is supposed to match the 95:64 bits of the IP, assume the caller is masking this correctly put the whole IP in the table.
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_ADDR_DST}},
Bytes: req.GetFieldDstIpv6Word2().GetDataIp(),
Masks: req.GetFieldDstIpv6Word2().GetMaskIp(),
})
}
if req.GetFieldDstMac() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_DST}},
Bytes: req.GetFieldDstMac().GetDataMac(),
Masks: req.GetFieldDstMac().GetMaskMac(),
})
}
if req.GetFieldEtherType() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_TYPE}},
Bytes: binary.BigEndian.AppendUint16(nil, uint16(req.GetFieldEtherType().GetDataUint())),
Masks: binary.BigEndian.AppendUint16(nil, uint16(req.GetFieldEtherType().GetMaskUint())),
})
}
if req.GetFieldIcmpv6Type() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ICMP_TYPE}},
Bytes: []byte{byte(req.GetFieldIcmpv6Type().GetDataUint())},
Masks: []byte{byte(req.GetFieldIcmpv6Type().GetMaskUint())},
})
}
if req.GetFieldIpProtocol() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_PROTO}},
Bytes: []byte{byte(req.GetFieldIpProtocol().GetDataUint())},
Masks: []byte{byte(req.GetFieldIpProtocol().GetMaskUint())},
})
}
if req.GetFieldL4DstPort() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_L4_PORT_DST}},
Bytes: binary.BigEndian.AppendUint16(nil, uint16(req.GetFieldL4DstPort().GetDataUint())),
Masks: binary.BigEndian.AppendUint16(nil, uint16(req.GetFieldL4DstPort().GetMaskUint())),
})
}
if req.GetFieldSrcMac() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_ETHER_MAC_SRC}},
Bytes: req.GetFieldSrcMac().GetDataMac(),
Masks: req.GetFieldSrcMac().GetMaskMac(),
})
}
if req.GetFieldTtl() != nil {
aReq.EntryDesc.GetFlow().Fields = append(aReq.EntryDesc.GetFlow().Fields, &fwdpb.PacketFieldMaskedBytes{
FieldId: &fwdpb.PacketFieldId{Field: &fwdpb.PacketField{FieldNum: fwdpb.PacketFieldNum_PACKET_FIELD_NUM_IP_HOP}},
Bytes: []byte{byte(req.GetFieldTtl().GetDataUint())},
Masks: []byte{byte(req.GetFieldTtl().GetMaskUint())},
})
}
if len(aReq.EntryDesc.GetFlow().Fields) == 0 {
return nil, status.Error(codes.InvalidArgument, "either no fields or not unsupports fields in entry req")
}
switch {
case req.ActionSetVrf != nil:
aReq.Actions = append(aReq.Actions,
Expand Down
Loading