Skip to content

Instantly share code, notes, and snippets.

@calmh
Created September 7, 2016 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save calmh/7cdd4e773806ab47e6931601108fbd30 to your computer and use it in GitHub Desktop.
Save calmh/7cdd4e773806ab47e6931601108fbd30 to your computer and use it in GitHub Desktop.
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