diff options
-rw-r--r-- | gobgp/cmd/global.go | 13 | ||||
-rw-r--r-- | packet/bgp/bgp.go | 70 |
2 files changed, 32 insertions, 51 deletions
diff --git a/gobgp/cmd/global.go b/gobgp/cmd/global.go index b5c46e74..5c720c4a 100644 --- a/gobgp/cmd/global.go +++ b/gobgp/cmd/global.go @@ -704,11 +704,14 @@ func ParsePath(rf bgp.RouteFamily, args []string) (*api.Path, error) { nlri, extcomms, err = ParseFlowSpecArgs(rf, args, rd) 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") + if len(m["key"]) != 1 { + return nil, fmt.Errorf("opaque nlri key missing") + } + if len(m["value"]) > 0 { + nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), []byte(m["value"][0])) + } else { + nlri = bgp.NewOpaqueNLRI([]byte(m["key"][0]), nil) } - 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) } @@ -837,7 +840,7 @@ usage: %s rib %s%%smatch <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) + 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/bgp.go b/packet/bgp/bgp.go index cd767937..798644ec 100644 --- a/packet/bgp/bgp.go +++ b/packet/bgp/bgp.go @@ -3354,24 +3354,32 @@ func NewFlowSpecL2VPN(rd RouteDistinguisherInterface, value []FlowSpecComponentI } type OpaqueNLRI struct { - Length uint8 + Length uint16 Key []byte + Value []byte } func (n *OpaqueNLRI) DecodeFromBytes(data []byte) error { - n.Length = data[0] - if len(data)-1 < int(n.Length) { + if len(data) < 2 { + return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all OpaqueNLRI bytes available") + } + n.Length = binary.BigEndian.Uint16(data[0:2]) + if len(data)-2 < int(n.Length) { return NewMessageError(BGP_ERROR_UPDATE_MESSAGE_ERROR, BGP_ERROR_SUB_MALFORMED_ATTRIBUTE_LIST, nil, "Not all OpaqueNLRI bytes available") } - n.Key = data[1 : 1+n.Length] + n.Key = data[2 : 2+n.Length] + n.Value = data[2+n.Length:] return nil } func (n *OpaqueNLRI) Serialize() ([]byte, error) { - if len(n.Key) > math.MaxUint8 { + if len(n.Key) > math.MaxUint16 { return nil, fmt.Errorf("Key length too big") } - return append([]byte{byte(len(n.Key))}, n.Key...), nil + buf := make([]byte, 2) + binary.BigEndian.PutUint16(buf, uint16(len(n.Key))) + buf = append(buf, n.Key...) + return append(buf, n.Value...), nil } func (n *OpaqueNLRI) AFI() uint16 { @@ -3383,24 +3391,27 @@ func (n *OpaqueNLRI) SAFI() uint8 { } func (n *OpaqueNLRI) Len() int { - return 1 + len(n.Key) + return 2 + len(n.Key) + len(n.Value) } func (n *OpaqueNLRI) String() string { - return string(n.Key) + return fmt.Sprintf("%s", n.Key) } func (n *OpaqueNLRI) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - Key string `json:"key"` + Key string `json:"key"` + Value string `json:"value"` }{ - Key: n.String(), + Key: string(n.Key), + Value: string(n.Value), }) } -func NewOpaqueNLRI(key []byte) *OpaqueNLRI { +func NewOpaqueNLRI(key, value []byte) *OpaqueNLRI { return &OpaqueNLRI{ - Key: key, + Key: key, + Value: value, } } @@ -3595,8 +3606,7 @@ const ( BGP_ATTR_TYPE_TUNNEL_ENCAP _ _ - BGP_ATTR_TYPE_AIGP // = 26 - BGP_ATTR_TYPE_OPAQUE_VALUE BGPAttrType = 41 + BGP_ATTR_TYPE_AIGP // = 26 ) // NOTIFICATION Error Code RFC 4271 4.5. @@ -3782,7 +3792,6 @@ 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 { @@ -6642,35 +6651,6 @@ 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 } @@ -6718,8 +6698,6 @@ 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 } |