diff options
-rw-r--r-- | config/bgp_configs.go | 3 | ||||
-rw-r--r-- | docs/sources/cli-command-syntax.md | 7 | ||||
-rw-r--r-- | gobgp/cmd/common.go | 2 | ||||
-rw-r--r-- | gobgp/cmd/global.go | 8 | ||||
-rw-r--r-- | packet/bgp.go | 106 | ||||
-rw-r--r-- | packet/routefamily_string.go | 63 | ||||
-rw-r--r-- | tools/pyang_plugins/gobgp.yang | 7 |
7 files changed, 126 insertions, 70 deletions
diff --git a/config/bgp_configs.go b/config/bgp_configs.go index 104d7d06..b5e18c5b 100644 --- a/config/bgp_configs.go +++ b/config/bgp_configs.go @@ -234,6 +234,7 @@ const ( AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC AfiSafiType = "l3vpn-ipv4-flowspec" AFI_SAFI_TYPE_IPV6_FLOWSPEC AfiSafiType = "ipv6-flowspec" AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC AfiSafiType = "l3vpn-ipv6-flowspec" + AFI_SAFI_TYPE_OPAQUE AfiSafiType = "opaque" ) var AfiSafiTypeToIntMap = map[AfiSafiType]int{ @@ -255,6 +256,7 @@ var AfiSafiTypeToIntMap = map[AfiSafiType]int{ AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC: 15, AFI_SAFI_TYPE_IPV6_FLOWSPEC: 16, AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC: 17, + AFI_SAFI_TYPE_OPAQUE: 18, } func (v AfiSafiType) ToInt() int { @@ -284,6 +286,7 @@ var IntToAfiSafiTypeMap = map[int]AfiSafiType{ 15: AFI_SAFI_TYPE_L3VPN_IPV4_FLOWSPEC, 16: AFI_SAFI_TYPE_IPV6_FLOWSPEC, 17: AFI_SAFI_TYPE_L3VPN_IPV6_FLOWSPEC, + 18: AFI_SAFI_TYPE_OPAQUE, } func (v AfiSafiType) Validate() error { diff --git a/docs/sources/cli-command-syntax.md b/docs/sources/cli-command-syntax.md index bd34e486..7034bfc8 100644 --- a/docs/sources/cli-command-syntax.md +++ b/docs/sources/cli-command-syntax.md @@ -72,6 +72,7 @@ If you want to remove routes with the address of the ipv6 from global rib: % gobgp global rib add -a vpnv4 10.0.0.0/24 rd 100.100:100 % gobgp global rib add -a vpnv4 10.0.0.0/24 rd 10.10.10.10:100 % gobgp global rib add -a vpnv4 10.0.0.0/24 rd 100:100 rt 100:200 +% gobgp global rib add -a opaque key hello value world ``` #### - option @@ -79,7 +80,7 @@ The following options can be specified in the global subcommand: | short |long | description | default | |--------|---------------|--------------------------------------------|---------| -|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeled`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec` | `ipv4` | +|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeled`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec`, `opaque` | `ipv4` | <br> @@ -109,7 +110,7 @@ The following options can be specified in the global subcommand: | short |long | description | default | |--------|---------------|--------------------------------------------|---------| -|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeld`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec` | `ipv4` | +|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeld`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec`, `opaque` | `ipv4` | ### 2.3. Show Rib - local-rib/adj-rib-in/adj-rib-out - #### - syntax @@ -131,7 +132,7 @@ The following options can be specified in the neighbor subcommand: | short |long | description | default | |--------|---------------|--------------------------------------------|---------| -|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeld`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec` | `ipv4` | +|a |address-family |specify any one from among `ipv4`, `ipv6`, `vpnv4`, `vpnv6`, `ipv4-labeled`, `ipv6-labeld`, `evpn`, `encap`, `rtc`, `ipv4-flowspec`, `ipv6-flowspec`, `opaque` | `ipv4` | ### 2.4. Operations for Policy - add/del/show - diff --git a/gobgp/cmd/common.go b/gobgp/cmd/common.go index c17185ad..8a53df48 100644 --- a/gobgp/cmd/common.go +++ b/gobgp/cmd/common.go @@ -456,6 +456,8 @@ func checkAddressFamily(def bgp.RouteFamily) (bgp.RouteFamily, error) { rf = bgp.RF_FS_IPv4_UC case "ipv6-flowspec", "ipv6-flow", "flow6": rf = bgp.RF_FS_IPv6_UC + case "opaque": + rf = bgp.RF_OPAQUE case "": rf = def default: diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index 0ad6a860..6b328ab1 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -648,6 +648,13 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) { nlri, extcomms, err = ParseEvpnArgs(args) case bgp.RF_FS_IPv4_UC, bgp.RF_FS_IPv6_UC: nlri, extcomms, err = ParseFlowSpecArgs(rf, args) + case bgp.RF_OPAQUE: + m := extractReserved(args, []string{"key", "value"}) + if len(m["key"]) != 1 || len(m["value"]) != 1 { + return nil, fmt.Errorf("invalid key-value format") + } + nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0])) + attrs = append(attrs, bgp.NewPathAttributeOpaqueValue([]byte(m["value"][0]))) default: return nil, fmt.Errorf("Unsupported route family: %s", rf) } @@ -748,6 +755,7 @@ usage: %s rib %s match <MATCH_EXPR> then <THEN_EXPR> -a %%s helpErrMap[bgp.RF_EVPN] = fmt.Errorf(`usage: %s rib %s { macadv <MACADV> | multicast <MULTICAST> } -a evpn <MACADV> : <mac address> <ip address> <etag> <label> rd <rd> rt <rt>... [encap <encap type>] <MULTICAST> : <ip address> <etag> rd <rd> rt <rt>... [encap <encap type>]`, cmdstr, modtype) + helpErrMap[bgp.RF_OPAQUE] = fmt.Errorf(`usage: %s rib %s key <KEY> value <VALUE>`, cmdstr, modtype) if err, ok := helpErrMap[rf]; ok { return err } diff --git a/packet/bgp.go b/packet/bgp.go index 1f0ee166..b899e8f2 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -29,9 +29,10 @@ import ( ) const ( - AFI_IP = 1 - AFI_IP6 = 2 - AFI_L2VPN = 25 + AFI_IP = 1 + AFI_IP6 = 2 + AFI_L2VPN = 25 + AFI_OPAQUE = 16397 ) const ( @@ -46,6 +47,7 @@ const ( SAFI_ROUTE_TARGET_CONSTRTAINS = 132 SAFI_FLOW_SPEC_UNICAST = 133 SAFI_FLOW_SPEC_VPN = 134 + SAFI_KEY_VALUE = 241 ) const ( @@ -2979,6 +2981,57 @@ func NewFlowSpecIPv6VPN(value []FlowSpecComponentInterface) *FlowSpecIPv6VPN { }} } +type OpaqueNLRI struct { + Length uint8 + Key []byte +} + +func (n *OpaqueNLRI) DecodeFromBytes(data []byte) error { + n.Length = data[0] + if len(data)-1 < int(n.Length) { + return fmt.Errorf("Not all OpaqueNLRI bytes available") + } + n.Key = data[1 : 1+n.Length] + return nil +} + +func (n *OpaqueNLRI) Serialize() ([]byte, error) { + if len(n.Key) > math.MaxUint8 { + return nil, fmt.Errorf("Key length too big") + } + return append([]byte{byte(len(n.Key))}, n.Key...), nil +} + +func (n *OpaqueNLRI) AFI() uint16 { + return AFI_OPAQUE +} + +func (n *OpaqueNLRI) SAFI() uint8 { + return SAFI_KEY_VALUE +} + +func (n *OpaqueNLRI) Len() int { + return 1 + len(n.Key) +} + +func (n *OpaqueNLRI) String() string { + return string(n.Key) +} + +func (n *OpaqueNLRI) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Key string `json:"key"` + }{ + Key: n.String(), + }) +} + +func NewOpaqueNLRI(key []byte) *OpaqueNLRI { + return &OpaqueNLRI{ + Key: key, + } +} + func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily { return RouteFamily(int(afi)<<16 | int(safi)) } @@ -2989,6 +3042,13 @@ func RouteFamilyToAfiSafi(rf RouteFamily) (uint16, uint8) { type RouteFamily int +func (f RouteFamily) String() string { + if n, y := AddressFamilyNameMap[f]; y { + return n + } + return fmt.Sprintf("UnknownFamily(%d)", f) +} + const ( RF_IPv4_UC RouteFamily = AFI_IP<<16 | SAFI_UNICAST RF_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_UNICAST @@ -3008,6 +3068,7 @@ const ( RF_FS_IPv4_VPN RouteFamily = AFI_IP<<16 | SAFI_FLOW_SPEC_VPN RF_FS_IPv6_UC RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_UNICAST RF_FS_IPv6_VPN RouteFamily = AFI_IP6<<16 | SAFI_FLOW_SPEC_VPN + RF_OPAQUE RouteFamily = AFI_OPAQUE<<16 | SAFI_KEY_VALUE ) var AddressFamilyNameMap = map[RouteFamily]string{ @@ -3029,6 +3090,7 @@ var AddressFamilyNameMap = map[RouteFamily]string{ RF_FS_IPv4_VPN: "l3vpn-ipv4-flowspec", RF_FS_IPv6_UC: "ipv6-flowspec", RF_FS_IPv6_VPN: "l3vpn-ipv6-flowspec", + RF_OPAQUE: "opaque", } var AddressFamilyValueMap = map[string]RouteFamily{ @@ -3050,6 +3112,7 @@ var AddressFamilyValueMap = map[string]RouteFamily{ AddressFamilyNameMap[RF_FS_IPv4_VPN]: RF_FS_IPv4_VPN, AddressFamilyNameMap[RF_FS_IPv6_UC]: RF_FS_IPv6_UC, AddressFamilyNameMap[RF_FS_IPv6_VPN]: RF_FS_IPv6_VPN, + AddressFamilyNameMap[RF_OPAQUE]: RF_OPAQUE, } func GetRouteFamily(name string) (RouteFamily, error) { @@ -3087,6 +3150,8 @@ func NewPrefixFromRouteFamily(afi uint16, safi uint8) (prefix AddrPrefixInterfac prefix = &FlowSpecIPv6Unicast{} case RF_FS_IPv6_VPN: prefix = &FlowSpecIPv6VPN{} + case RF_OPAQUE: + prefix = &OpaqueNLRI{} default: return nil, fmt.Errorf("unknown route family. AFI: %d, SAFI: %d", afi, safi) } @@ -3148,7 +3213,8 @@ const ( BGP_ATTR_TYPE_TUNNEL_ENCAP _ _ - BGP_ATTR_TYPE_AIGP // = 26 + BGP_ATTR_TYPE_AIGP // = 26 + BGP_ATTR_TYPE_OPAQUE_VALUE BGPAttrType = 41 ) // NOTIFICATION Error Code RFC 4271 4.5. @@ -3241,6 +3307,7 @@ var pathAttrFlags map[BGPAttrType]BGPAttrFlag = map[BGPAttrType]BGPAttrFlag{ BGP_ATTR_TYPE_PMSI_TUNNEL: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_TUNNEL_ENCAP: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, BGP_ATTR_TYPE_AIGP: BGP_ATTR_FLAG_OPTIONAL, + BGP_ATTR_TYPE_OPAQUE_VALUE: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, } type PathAttributeInterface interface { @@ -6085,6 +6152,35 @@ func NewPathAttributeAigp(values []AigpTLV) *PathAttributeAigp { } } +type PathAttributeOpaqueValue struct { + PathAttribute +} + +func (p *PathAttributeOpaqueValue) String() string { + return fmt.Sprintf("{Value: %s}", string(p.Value)) +} + +func (p *PathAttributeOpaqueValue) MarshalJSON() ([]byte, error) { + return json.Marshal(struct { + Type BGPAttrType `json:"type"` + Value string `json:"value"` + }{ + Type: p.GetType(), + Value: string(p.Value), + }) +} + +func NewPathAttributeOpaqueValue(value []byte) *PathAttributeOpaqueValue { + t := BGP_ATTR_TYPE_OPAQUE_VALUE + return &PathAttributeOpaqueValue{ + PathAttribute: PathAttribute{ + Flags: pathAttrFlags[t], + Type: t, + Value: value, + }, + } +} + type PathAttributeUnknown struct { PathAttribute } @@ -6132,6 +6228,8 @@ func GetPathAttribute(data []byte) (PathAttributeInterface, error) { return &PathAttributePmsiTunnel{}, nil case BGP_ATTR_TYPE_AIGP: return &PathAttributeAigp{}, nil + case BGP_ATTR_TYPE_OPAQUE_VALUE: + return &PathAttributeOpaqueValue{}, nil } return &PathAttributeUnknown{}, nil } diff --git a/packet/routefamily_string.go b/packet/routefamily_string.go deleted file mode 100644 index 8d718e1d..00000000 --- a/packet/routefamily_string.go +++ /dev/null @@ -1,63 +0,0 @@ -// generated by stringer -type=RouteFamily bgp.go validate.go constant.go; DO NOT EDIT - -package bgp - -import "fmt" - -const ( - _RouteFamily_name_0 = "RF_IPv4_UCRF_IPv4_MC" - _RouteFamily_name_1 = "RF_IPv4_MPLS" - _RouteFamily_name_2 = "RF_ENCAP" - _RouteFamily_name_3 = "RF_IPv4_VPNRF_IPv4_VPN_MC" - _RouteFamily_name_4 = "RF_RTC_UCRF_FS_IPv4_UCRF_FS_IPv4_VPN" - _RouteFamily_name_5 = "RF_IPv6_UCRF_IPv6_MC" - _RouteFamily_name_6 = "RF_IPv6_MPLS" - _RouteFamily_name_7 = "RF_IPv6_VPNRF_IPv6_VPN_MC" - _RouteFamily_name_8 = "RF_VPLS" - _RouteFamily_name_9 = "RF_EVPN" -) - -var ( - _RouteFamily_index_0 = [...]uint8{0, 10, 20} - _RouteFamily_index_1 = [...]uint8{0, 12} - _RouteFamily_index_2 = [...]uint8{0, 8} - _RouteFamily_index_3 = [...]uint8{0, 11, 25} - _RouteFamily_index_4 = [...]uint8{0, 9, 22, 36} - _RouteFamily_index_5 = [...]uint8{0, 10, 20} - _RouteFamily_index_6 = [...]uint8{0, 12} - _RouteFamily_index_7 = [...]uint8{0, 11, 25} - _RouteFamily_index_8 = [...]uint8{0, 7} - _RouteFamily_index_9 = [...]uint8{0, 7} -) - -func (i RouteFamily) String() string { - switch { - case 65537 <= i && i <= 65538: - i -= 65537 - return _RouteFamily_name_0[_RouteFamily_index_0[i]:_RouteFamily_index_0[i+1]] - case i == 65540: - return _RouteFamily_name_1 - case i == 65543: - return _RouteFamily_name_2 - case 65664 <= i && i <= 65665: - i -= 65664 - return _RouteFamily_name_3[_RouteFamily_index_3[i]:_RouteFamily_index_3[i+1]] - case 65668 <= i && i <= 65670: - i -= 65668 - return _RouteFamily_name_4[_RouteFamily_index_4[i]:_RouteFamily_index_4[i+1]] - case 131073 <= i && i <= 131074: - i -= 131073 - return _RouteFamily_name_5[_RouteFamily_index_5[i]:_RouteFamily_index_5[i+1]] - case i == 131076: - return _RouteFamily_name_6 - case 131200 <= i && i <= 131201: - i -= 131200 - return _RouteFamily_name_7[_RouteFamily_index_7[i]:_RouteFamily_index_7[i+1]] - case i == 1638465: - return _RouteFamily_name_8 - case i == 1638470: - return _RouteFamily_name_9 - default: - return fmt.Sprintf("RouteFamily(%d)", i) - } -} diff --git a/tools/pyang_plugins/gobgp.yang b/tools/pyang_plugins/gobgp.yang index e7dc1dcd..a15fe80d 100644 --- a/tools/pyang_plugins/gobgp.yang +++ b/tools/pyang_plugins/gobgp.yang @@ -119,6 +119,13 @@ module gobgp { reference "RFC5575"; } + identity OPAQUE { + base bgp-types:afi-safi-type; + description + "Opaque (AFI,SAFI = 16397,241)"; + reference "https://tools.ietf.org/html/draft-lapukhov-bgp-opaque-signaling-01"; + } + grouping gobgp-message-counter { description "Counters for all BGPMessage types"; |