Skip to content
Snippets Groups Projects
Unverified Commit b0365eba authored by Daniel Czerwonk's avatar Daniel Czerwonk Committed by GitHub
Browse files

Merge pull request #28 from hikhvar/feature/add-basic-communities

Feature: Added basic community support
parents 46a2f9bb 5edae50b
Branches
Tags
No related merge requests found
......@@ -55,13 +55,14 @@ const (
AdministrativeReset = 4
// Attribute Type Codes
OriginAttr = 1
ASPathAttr = 2
NextHopAttr = 3
MEDAttr = 4
LocalPrefAttr = 5
AtomicAggrAttr = 6
AggregatorAttr = 7
OriginAttr = 1
ASPathAttr = 2
NextHopAttr = 3
MEDAttr = 4
LocalPrefAttr = 5
AtomicAggrAttr = 6
AggregatorAttr = 7
CommunitiesAttr = 8
// ORIGIN values
IGP = 0
......
......@@ -651,7 +651,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
3, // Attribute Type code (Next Hop)
4, // Length
10, 11, 12, 13, // Next Hop
},
wantFail: false,
expected: &BGPUpdate{
......@@ -745,7 +744,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
4, // Attribute Type code (Next Hop)
4, // Length
0, 0, 1, 0, // MED 256
},
wantFail: false,
expected: &BGPUpdate{
......@@ -852,7 +850,6 @@ func TestDecodeUpdateMsg(t *testing.T) {
5, // Attribute Type code (Local Pref)
4, // Length
0, 0, 1, 0, // Local Pref 256
},
wantFail: false,
expected: &BGPUpdate{
......@@ -1262,6 +1259,94 @@ func TestDecodeUpdateMsg(t *testing.T) {
},
},
},
{
// 2 withdraws with two path attributes (Communities + Origin), valid update
testNum: 17,
input: []byte{0, 5, 8, 10, 16, 192, 168,
0, 16, // Total Path Attribute Length
0, // Attribute flags
8, // Attribute Type code (Community)
8, // Length
0, 0, 1, 0, // Arbitrary Community
0, 0, 1, 1, // Arbitrary Community
255, // Attribute flags
1, // Attribute Type code (ORIGIN)
0, 1, // Length
2, // INCOMPLETE
},
wantFail: false,
expected: &BGPUpdate{
WithdrawnRoutesLen: 5,
WithdrawnRoutes: &NLRI{
IP: strAddr("10.0.0.0"),
Pfxlen: 8,
Next: &NLRI{
IP: strAddr("192.168.0.0"),
Pfxlen: 16,
},
},
TotalPathAttrLen: 16,
PathAttributes: &PathAttribute{
Optional: false,
Transitive: false,
Partial: false,
ExtendedLength: false,
Length: 8,
TypeCode: 8,
Value: []uint32{256, 257},
Next: &PathAttribute{
Optional: true,
Transitive: true,
Partial: true,
ExtendedLength: true,
Length: 1,
TypeCode: 1,
Value: uint8(2),
},
},
},
},
{
// 2 withdraws with two path attributes (ORIGIN + Community), invalid update (too short community)
testNum: 18,
input: []byte{0, 5, 8, 10, 16, 192, 168,
0, 11, // Total Path Attribute Length
255, // Attribute flags
1, // Attribute Type code (ORIGIN)
0, 1, // Length
2, // INCOMPLETE
0, // Attribute flags
8, // Attribute Type code (Community)
3, // Length
0, 0, 1, // Arbitrary Community
},
wantFail: true,
expected: nil,
},
{
// 2 withdraws with two path attributes (ORIGIN + Community), invalid update (too long community)
testNum: 19,
input: []byte{0, 5, 8, 10, 16, 192, 168,
0, 13, // Total Path Attribute Length
255, // Attribute flags
1, // Attribute Type code (ORIGIN)
0, 1, // Length
2, // INCOMPLETE
0, // Attribute flags
8, // Attribute Type code (Community)
5, // Length
0, 0, 1, 0, 1, // Arbitrary Community
},
wantFail: true,
expected: nil,
},
}
for _, test := range tests {
......
......@@ -84,6 +84,10 @@ func decodePathAttr(buf *bytes.Buffer) (pa *PathAttribute, consumed uint16, err
}
case AtomicAggrAttr:
// Nothing to do for 0 octet long attribute
case CommunitiesAttr:
if err := pa.decodeCommunities(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode Community: %v", err)
}
default:
if err := pa.decodeUnknown(buf); err != nil {
return nil, consumed, fmt.Errorf("Failed to decode unknown attribute: %v", err)
......@@ -227,6 +231,27 @@ func (pa *PathAttribute) decodeAggregator(buf *bytes.Buffer) error {
return dumpNBytes(buf, pa.Length-p)
}
func (pa *PathAttribute) decodeCommunities(buf *bytes.Buffer) error {
if pa.Length%4 != 0 {
return fmt.Errorf("Unable to read community path attribute length %d is not divisible by 4", pa.Length)
}
comNumber := pa.Length / 4
var com = make([]uint32, comNumber)
for i := uint16(0); i < comNumber; i++ {
c := [4]byte{}
n, err := buf.Read(c[:])
if err != nil {
return err
}
if n != 4 {
return fmt.Errorf("Unable to read next hop: buf.Read read %d bytes", n)
}
com[i] = fourBytesToUint32(c)
}
pa.Value = com
return nil
}
func (pa *PathAttribute) setLength(buf *bytes.Buffer) (int, error) {
bytesRead := 0
if pa.ExtendedLength {
......
......@@ -789,8 +789,7 @@ func (fsm *FSM) established() int {
case recvMsg := <-fsm.msgRecvCh:
msg, err := packet.Decode(bytes.NewBuffer(recvMsg.msg))
if err != nil {
log.WithError(err).Errorf("Failed to decode BGP message %v\n", recvMsg.msg)
log.WithError(err).Errorf("Failed to decode BGP message %v\n", recvMsg.msg)
switch bgperr := err.(type) {
case packet.BGPError:
sendNotification(fsm.con, bgperr.ErrorCode, bgperr.ErrorSubCode)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment