summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorWataru Ishida <ishida.wataru@lab.ntt.co.jp>2016-09-08 02:08:45 +0000
committerFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2016-09-14 11:35:50 +0900
commit6eb19da9651337ab38719468b1315b9950d3dcb3 (patch)
treede4fe78dbced25ae3c9253283ac07f168c3f1108
parent22f888766aba3eb39fc50f0161537221ed0c5f6a (diff)
bgp: support latest Opaque Signaling draft
see https://tools.ietf.org/html/draft-lapukhov-bgp-opaque-signaling-02 $ gobgp global rib -a opaque add key hello value world $ gobgp global rib -a opaque del key hello Signed-off-by: Wataru Ishida <ishida.wataru@lab.ntt.co.jp>
-rw-r--r--gobgp/cmd/global.go13
-rw-r--r--packet/bgp/bgp.go70
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
}