diff options
-rw-r--r-- | gobgp/cmd/global.go | 27 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 58 | ||||
-rw-r--r-- | packet/bgp/bgp_test.go | 17 | ||||
-rw-r--r-- | packet/bgp/validate_test.go | 6 | ||||
-rw-r--r-- | table/path.go | 33 |
5 files changed, 66 insertions, 75 deletions
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index 4922875a..6ab87024 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -25,10 +25,11 @@ import ( "strings" "time" + "github.com/spf13/cobra" + "github.com/osrg/gobgp/config" "github.com/osrg/gobgp/packet/bgp" "github.com/osrg/gobgp/table" - "github.com/spf13/cobra" ) type ExtCommType int @@ -334,34 +335,28 @@ func ParseFlowSpecArgs(rf bgp.RouteFamily, args []string, rd bgp.RouteDistinguis return nil, nil, fmt.Errorf("invalid format") } matchArgs := args[1:thenPos] - cmp, err := bgp.ParseFlowSpecComponents(rf, strings.Join(matchArgs, " ")) + + rules, err := bgp.ParseFlowSpecComponents(rf, strings.Join(matchArgs, " ")) if err != nil { return nil, nil, err } + var nlri bgp.AddrPrefixInterface - var fnlri *bgp.FlowSpecNLRI switch rf { case bgp.RF_FS_IPv4_UC: - nlri = bgp.NewFlowSpecIPv4Unicast(cmp) - fnlri = &nlri.(*bgp.FlowSpecIPv4Unicast).FlowSpecNLRI + nlri = bgp.NewFlowSpecIPv4Unicast(rules) case bgp.RF_FS_IPv6_UC: - nlri = bgp.NewFlowSpecIPv6Unicast(cmp) - fnlri = &nlri.(*bgp.FlowSpecIPv6Unicast).FlowSpecNLRI + nlri = bgp.NewFlowSpecIPv6Unicast(rules) case bgp.RF_FS_IPv4_VPN: - nlri = bgp.NewFlowSpecIPv4VPN(rd, cmp) - fnlri = &nlri.(*bgp.FlowSpecIPv4VPN).FlowSpecNLRI + nlri = bgp.NewFlowSpecIPv4VPN(rd, rules) case bgp.RF_FS_IPv6_VPN: - nlri = bgp.NewFlowSpecIPv6VPN(rd, cmp) - fnlri = &nlri.(*bgp.FlowSpecIPv6VPN).FlowSpecNLRI + nlri = bgp.NewFlowSpecIPv6VPN(rd, rules) case bgp.RF_FS_L2_VPN: - nlri = bgp.NewFlowSpecL2VPN(rd, cmp) - fnlri = &nlri.(*bgp.FlowSpecL2VPN).FlowSpecNLRI + nlri = bgp.NewFlowSpecL2VPN(rd, rules) default: return nil, nil, fmt.Errorf("invalid route family") } - var comms table.FlowSpecComponents - comms = fnlri.Value - sort.Sort(comms) + return nlri, args[thenPos+1:], nil } diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go index ef31817c..987bf328 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -4027,6 +4027,10 @@ func (n *FlowSpecNLRI) decodeFromBytes(rf RouteFamily, data []byte, options ...* n.Value = append(n.Value, i) } + // Sort Traffic Filtering Rules in types order to avoid the unordered rules + // are determined different. + sort.SliceStable(n.Value, func(i, j int) bool { return n.Value[i].Type() < n.Value[j].Type() }) + return nil } @@ -4246,7 +4250,13 @@ func (n *FlowSpecIPv4Unicast) DecodeFromBytes(data []byte, options ...*Marshalli } func NewFlowSpecIPv4Unicast(value []FlowSpecComponentInterface) *FlowSpecIPv4Unicast { - return &FlowSpecIPv4Unicast{FlowSpecNLRI{Value: value, rf: RF_FS_IPv4_UC}} + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv4Unicast{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv4_UC, + }, + } } type FlowSpecIPv4VPN struct { @@ -4258,7 +4268,14 @@ func (n *FlowSpecIPv4VPN) DecodeFromBytes(data []byte, options ...*MarshallingOp } func NewFlowSpecIPv4VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecIPv4VPN { - return &FlowSpecIPv4VPN{FlowSpecNLRI{Value: value, rf: RF_FS_IPv4_VPN, rd: rd}} + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv4VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv4_VPN, + rd: rd, + }, + } } type FlowSpecIPv6Unicast struct { @@ -4270,10 +4287,13 @@ func (n *FlowSpecIPv6Unicast) DecodeFromBytes(data []byte, options ...*Marshalli } func NewFlowSpecIPv6Unicast(value []FlowSpecComponentInterface) *FlowSpecIPv6Unicast { - return &FlowSpecIPv6Unicast{FlowSpecNLRI{ - Value: value, - rf: RF_FS_IPv6_UC, - }} + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv6Unicast{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv6_UC, + }, + } } type FlowSpecIPv6VPN struct { @@ -4285,11 +4305,14 @@ func (n *FlowSpecIPv6VPN) DecodeFromBytes(data []byte, options ...*MarshallingOp } func NewFlowSpecIPv6VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecIPv6VPN { - return &FlowSpecIPv6VPN{FlowSpecNLRI{ - Value: value, - rf: RF_FS_IPv6_VPN, - rd: rd, - }} + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecIPv6VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_IPv6_VPN, + rd: rd, + }, + } } type FlowSpecL2VPN struct { @@ -4301,11 +4324,14 @@ func (n *FlowSpecL2VPN) DecodeFromBytes(data []byte, options ...*MarshallingOpti } func NewFlowSpecL2VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentInterface) *FlowSpecL2VPN { - return &FlowSpecL2VPN{FlowSpecNLRI{ - Value: value, - rf: RF_FS_L2_VPN, - rd: rd, - }} + sort.SliceStable(value, func(i, j int) bool { return value[i].Type() < value[j].Type() }) + return &FlowSpecL2VPN{ + FlowSpecNLRI: FlowSpecNLRI{ + Value: value, + rf: RF_FS_L2_VPN, + rd: rd, + }, + } } type OpaqueNLRI struct { diff --git a/packet/bgp/bgp_test.go b/packet/bgp/bgp_test.go index c3833fa8..d3e2719f 100644 --- a/packet/bgp/bgp_test.go +++ b/packet/bgp/bgp_test.go @@ -787,20 +787,21 @@ func Test_CompareFlowSpecNLRI(t *testing.T) { assert := assert.New(t) cmp, err := ParseFlowSpecComponents(RF_FS_IPv4_UC, "destination 10.0.0.2/32 source 10.0.0.1/32 destination-port ==3128 protocol tcp") assert.Nil(err) - n1 := &FlowSpecNLRI{Value: cmp, rf: RF_FS_IPv4_UC} + // Note: Use NewFlowSpecIPv4Unicast() for the consistent ordered rules. + n1 := NewFlowSpecIPv4Unicast(cmp).FlowSpecNLRI cmp, err = ParseFlowSpecComponents(RF_FS_IPv4_UC, "source 10.0.0.0/24 destination-port ==3128 protocol tcp") assert.Nil(err) - n2 := &FlowSpecNLRI{Value: cmp, rf: RF_FS_IPv4_UC} + n2 := NewFlowSpecIPv4Unicast(cmp).FlowSpecNLRI + r, err := CompareFlowSpecNLRI(&n1, &n2) + assert.Nil(err) + assert.True(r > 0) cmp, err = ParseFlowSpecComponents(RF_FS_IPv4_UC, "source 10.0.0.9/32 port ==80 ==8080 destination-port >8080&<8080 ==3128 source-port >1024 protocol ==udp ==tcp") - n3 := &FlowSpecNLRI{Value: cmp, rf: RF_FS_IPv4_UC} + n3 := NewFlowSpecIPv4Unicast(cmp).FlowSpecNLRI assert.Nil(err) cmp, err = ParseFlowSpecComponents(RF_FS_IPv4_UC, "destination 192.168.0.2/32") - n4 := &FlowSpecNLRI{Value: cmp, rf: RF_FS_IPv4_UC} + n4 := NewFlowSpecIPv4Unicast(cmp).FlowSpecNLRI assert.Nil(err) - r, err := CompareFlowSpecNLRI(n1, n2) - assert.Nil(err) - assert.True(r > 0) - r, err = CompareFlowSpecNLRI(n3, n4) + r, err = CompareFlowSpecNLRI(&n3, &n4) assert.Nil(err) assert.True(r < 0) } diff --git a/packet/bgp/validate_test.go b/packet/bgp/validate_test.go index 3bb60639..12f81e03 100644 --- a/packet/bgp/validate_test.go +++ b/packet/bgp/validate_test.go @@ -388,8 +388,8 @@ func Test_Validate_flowspec(t *testing.T) { cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_TCP_FLAG, []*FlowSpecComponentItem{item5, item6})) cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_PKT_LEN, []*FlowSpecComponentItem{item2, item3, item4})) cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_DSCP, []*FlowSpecComponentItem{item2, item3, item4})) - isFlagment := 0x02 - item7 := NewFlowSpecComponentItem(isFlagment, 0) + isFragment := 0x02 + item7 := NewFlowSpecComponentItem(isFragment, 0) cmp = append(cmp, NewFlowSpecComponent(FLOW_SPEC_TYPE_FRAGMENT, []*FlowSpecComponentItem{item7})) n1 := NewFlowSpecIPv4Unicast(cmp) a := NewPathAttributeMpReachNLRI("", []AddrPrefixInterface{n1}) @@ -402,6 +402,8 @@ func Test_Validate_flowspec(t *testing.T) { cmp = append(cmp, NewFlowSpecDestinationPrefix(NewIPAddrPrefix(24, "10.0.0.0"))) n1 = NewFlowSpecIPv4Unicast(cmp) a = NewPathAttributeMpReachNLRI("", []AddrPrefixInterface{n1}) + // Swaps components order to reproduce the rules order violation. + n1.Value[0], n1.Value[1] = n1.Value[1], n1.Value[0] _, err = ValidateAttribute(a, m, false, false) assert.NotNil(err) } diff --git a/table/path.go b/table/path.go index cf4603f2..9f041786 100644 --- a/table/path.go +++ b/table/path.go @@ -136,20 +136,6 @@ type Validation struct { UnmatchedLength []*ROA } -type FlowSpecComponents []bgp.FlowSpecComponentInterface - -func (c FlowSpecComponents) Len() int { - return len(c) -} - -func (c FlowSpecComponents) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} - -func (c FlowSpecComponents) Less(i, j int) bool { - return c[i].Type() < c[j].Type() -} - type Path struct { info *originInfo IsWithdraw bool @@ -173,25 +159,6 @@ func NewPath(source *PeerInfo, nlri bgp.AddrPrefixInterface, isWithdraw bool, pa return nil } - if nlri != nil && (nlri.SAFI() == bgp.SAFI_FLOW_SPEC_UNICAST || nlri.SAFI() == bgp.SAFI_FLOW_SPEC_VPN) { - var coms FlowSpecComponents - var f *bgp.FlowSpecNLRI - switch nlri.(type) { - case *bgp.FlowSpecIPv4Unicast: - f = &nlri.(*bgp.FlowSpecIPv4Unicast).FlowSpecNLRI - case *bgp.FlowSpecIPv4VPN: - f = &nlri.(*bgp.FlowSpecIPv4VPN).FlowSpecNLRI - case *bgp.FlowSpecIPv6Unicast: - f = &nlri.(*bgp.FlowSpecIPv6Unicast).FlowSpecNLRI - case *bgp.FlowSpecIPv6VPN: - f = &nlri.(*bgp.FlowSpecIPv6VPN).FlowSpecNLRI - } - if f != nil { - coms = f.Value - sort.Sort(coms) - } - } - return &Path{ info: &originInfo{ nlri: nlri, |