-
-
Save calmh/7cdd4e773806ab47e6931601108fbd30 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
config/bgp_configs.go | 6 ++++ | |
packet/bgp/bgp.go | 76 +++++++++++++++++++++++++++++++++++++++----------- | |
packet/bgp/bgp_test.go | 35 ++++++++++++++++++++++- | |
3 files changed, 99 insertions(+), 18 deletions(-) | |
diff --git a/config/bgp_configs.go b/config/bgp_configs.go | |
index 7125db4..c99342b 100644 | |
--- a/config/bgp_configs.go | |
+++ b/config/bgp_configs.go | |
@@ -83,6 +83,7 @@ const ( | |
COMMUNITY_TYPE_EXTENDED CommunityType = "extended" | |
COMMUNITY_TYPE_BOTH CommunityType = "both" | |
COMMUNITY_TYPE_NONE CommunityType = "none" | |
+ COMMUNITY_TYPE_LARGE CommunityType = "large" | |
) | |
var CommunityTypeToIntMap = map[CommunityType]int{ | |
@@ -90,6 +91,7 @@ var CommunityTypeToIntMap = map[CommunityType]int{ | |
COMMUNITY_TYPE_EXTENDED: 1, | |
COMMUNITY_TYPE_BOTH: 2, | |
COMMUNITY_TYPE_NONE: 3, | |
+ COMMUNITY_TYPE_LARGE: 4, | |
} | |
func (v CommunityType) ToInt() int { | |
@@ -105,6 +107,7 @@ var IntToCommunityTypeMap = map[int]CommunityType{ | |
1: COMMUNITY_TYPE_EXTENDED, | |
2: COMMUNITY_TYPE_BOTH, | |
3: COMMUNITY_TYPE_NONE, | |
+ 4: COMMUNITY_TYPE_LARGE, | |
} | |
func (v CommunityType) Validate() error { | |
@@ -120,6 +123,9 @@ type BgpExtCommunityType string | |
// typedef for typedef bgp-types:bgp-std-community-type | |
type BgpStdCommunityType string | |
+// typedef for typedef bgp-types:bgp-large-community-type | |
+type BgpLargeCommunityType string | |
+ | |
// typedef for identity bgp-types:peer-type | |
type PeerType string | |
diff --git a/packet/bgp/bgp.go b/packet/bgp/bgp.go | |
index cd76793..4ace27d 100644 | |
--- a/packet/bgp/bgp.go | |
+++ b/packet/bgp/bgp.go | |
@@ -3595,8 +3595,8 @@ const ( | |
BGP_ATTR_TYPE_TUNNEL_ENCAP | |
_ | |
_ | |
- BGP_ATTR_TYPE_AIGP // = 26 | |
- BGP_ATTR_TYPE_OPAQUE_VALUE BGPAttrType = 41 | |
+ BGP_ATTR_TYPE_AIGP // = 26 | |
+ BGP_ATTR_TYPE_LARGE_COMMUNITY BGPAttrType = 41 | |
) | |
// NOTIFICATION Error Code RFC 4271 4.5. | |
@@ -3782,7 +3782,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, | |
+ BGP_ATTR_TYPE_LARGE_COMMUNITY: BGP_ATTR_FLAG_TRANSITIVE | BGP_ATTR_FLAG_OPTIONAL, | |
} | |
type PathAttributeInterface interface { | |
@@ -6642,32 +6642,74 @@ func NewPathAttributeAigp(values []AigpTLV) *PathAttributeAigp { | |
} | |
} | |
-type PathAttributeOpaqueValue struct { | |
+type PathAttributeLargeCommunity struct { | |
PathAttribute | |
+ Values []LargeCommunity | |
} | |
-func (p *PathAttributeOpaqueValue) String() string { | |
- return fmt.Sprintf("{Value: %s}", string(p.Value)) | |
+const largeCommunityValueLen = 12 | |
+ | |
+type LargeCommunity struct { | |
+ ASN uint32 | |
+ Local1 uint32 | |
+ Local2 uint32 | |
} | |
-func (p *PathAttributeOpaqueValue) MarshalJSON() ([]byte, error) { | |
+func (p *PathAttributeLargeCommunity) DecodeFromBytes(data []byte) error { | |
+ err := p.PathAttribute.DecodeFromBytes(data) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ if len(p.Value)%largeCommunityValueLen != 0 { | |
+ return fmt.Errorf("PathAttributeLargeCommunity: length %d is not a multiple of 12 bytes", len(p.Value)) | |
+ } | |
+ | |
+ p.Values = make([]LargeCommunity, len(p.Value)/largeCommunityValueLen) | |
+ for i := 0; i < len(p.Value); i += largeCommunityValueLen { | |
+ var c LargeCommunity | |
+ c.ASN = binary.BigEndian.Uint32(p.Value[i:]) | |
+ c.Local1 = binary.BigEndian.Uint32(p.Value[i+4:]) | |
+ c.Local2 = binary.BigEndian.Uint32(p.Value[i+8:]) | |
+ p.Values[i/largeCommunityValueLen] = c | |
+ } | |
+ | |
+ return nil | |
+} | |
+ | |
+func (p *PathAttributeLargeCommunity) Serialize() ([]byte, error) { | |
+ buf := make([]byte, largeCommunityValueLen*len(p.Values)) | |
+ for i, v := range p.Values { | |
+ binary.BigEndian.PutUint32(buf[i*largeCommunityValueLen:], v.ASN) | |
+ binary.BigEndian.PutUint32(buf[i*largeCommunityValueLen+4:], v.Local1) | |
+ binary.BigEndian.PutUint32(buf[i*largeCommunityValueLen+8:], v.Local2) | |
+ } | |
+ p.PathAttribute.Value = buf | |
+ return p.PathAttribute.Serialize() | |
+} | |
+ | |
+func (p *PathAttributeLargeCommunity) String() string { | |
+ return fmt.Sprintf("{Values: %v}", p.Values) | |
+} | |
+ | |
+func (p *PathAttributeLargeCommunity) MarshalJSON() ([]byte, error) { | |
return json.Marshal(struct { | |
- Type BGPAttrType `json:"type"` | |
- Value string `json:"value"` | |
+ Type BGPAttrType `json:"type"` | |
+ Values []LargeCommunity `json:"values"` | |
}{ | |
- Type: p.GetType(), | |
- Value: string(p.Value), | |
+ Type: p.GetType(), | |
+ Values: p.Values, | |
}) | |
} | |
-func NewPathAttributeOpaqueValue(value []byte) *PathAttributeOpaqueValue { | |
- t := BGP_ATTR_TYPE_OPAQUE_VALUE | |
- return &PathAttributeOpaqueValue{ | |
+func NewPathAttributeLargeCommunity(values []LargeCommunity) *PathAttributeLargeCommunity { | |
+ t := BGP_ATTR_TYPE_LARGE_COMMUNITY | |
+ return &PathAttributeLargeCommunity{ | |
PathAttribute: PathAttribute{ | |
Flags: PathAttrFlags[t], | |
Type: t, | |
- Value: value, | |
}, | |
+ Values: values, | |
} | |
} | |
@@ -6718,8 +6760,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 | |
+ case BGP_ATTR_TYPE_LARGE_COMMUNITY: | |
+ return &PathAttributeLargeCommunity{}, nil | |
} | |
return &PathAttributeUnknown{}, nil | |
} | |
diff --git a/packet/bgp/bgp_test.go b/packet/bgp/bgp_test.go | |
index 80dcc5a..18da954 100644 | |
--- a/packet/bgp/bgp_test.go | |
+++ b/packet/bgp/bgp_test.go | |
@@ -18,10 +18,11 @@ package bgp | |
import ( | |
"bytes" | |
"encoding/binary" | |
- "github.com/stretchr/testify/assert" | |
"net" | |
"reflect" | |
"testing" | |
+ | |
+ "github.com/stretchr/testify/assert" | |
) | |
func keepalive() *BGPMessage { | |
@@ -480,3 +481,35 @@ func Test_FlowSpecNlriVPN(t *testing.T) { | |
t.Log(bytes.Equal(buf1, buf2)) | |
} | |
} | |
+ | |
+func Test_LargeCommunity(t *testing.T) { | |
+ assert := assert.New(t) | |
+ cs := []LargeCommunity{ | |
+ {42, 43, 44}, | |
+ {4294967295, 4294967294, 4294967293}, | |
+ } | |
+ | |
+ a1 := NewPathAttributeLargeCommunity(cs) | |
+ buf1, err := a1.Serialize() | |
+ assert.Nil(err) | |
+ | |
+ a2 := NewPathAttributeLargeCommunity(nil) | |
+ err = a2.DecodeFromBytes(buf1) | |
+ assert.Nil(err) | |
+ | |
+ buf2, _ := a2.Serialize() | |
+ if reflect.DeepEqual(a1, a2) == true { | |
+ t.Log("OK") | |
+ } else { | |
+ t.Error("Something wrong") | |
+ t.Error(len(buf1), a1, buf1) | |
+ t.Error(len(buf2), a2, buf2) | |
+ t.Log(bytes.Equal(buf1, buf2)) | |
+ } | |
+ | |
+ for i := range cs { | |
+ if cs[i] != a2.Values[i] { | |
+ t.Errorf("%d: %d != %d", i, cs[i], a2.Values[i]) | |
+ } | |
+ } | |
+} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment