summaryrefslogtreecommitdiffhomepage
path: root/packet
diff options
context:
space:
mode:
Diffstat (limited to 'packet')
-rw-r--r--packet/bgp.go124
1 files changed, 88 insertions, 36 deletions
diff --git a/packet/bgp.go b/packet/bgp.go
index 44f562eb..1b5cbbb5 100644
--- a/packet/bgp.go
+++ b/packet/bgp.go
@@ -16,6 +16,7 @@
package bgp
import (
+ "bytes"
"encoding/binary"
"encoding/json"
"errors"
@@ -970,27 +971,69 @@ func (n *RouteTargetMembershipNLRI) String() string {
return fmt.Sprintf("%d:%s/%d", n.AS, n.RouteTarget.String(), n.Len()*8)
}
+type ESIType uint8
+
+const (
+ ESI_ARBITRARY ESIType = iota
+ ESI_LACP
+ ESI_MSTP
+ ESI_MAC
+ ESI_ROUTERID
+ ESI_AS
+)
+
type EthernetSegmentIdentifier struct {
- Type uint8
+ Type ESIType
Value []byte
}
func (esi *EthernetSegmentIdentifier) DecodeFromBytes(data []byte) error {
- esi.Type = data[0]
+ esi.Type = ESIType(data[0])
esi.Value = data[1:10]
+ switch esi.Type {
+ case ESI_LACP, ESI_MSTP, ESI_ROUTERID, ESI_AS:
+ if esi.Value[8] != 0x00 {
+ return fmt.Errorf("invalid %s. last octet must be 0x00 (0x%02x)", esi.Type, esi.Value[8])
+ }
+ }
return nil
}
func (esi *EthernetSegmentIdentifier) Serialize() ([]byte, error) {
buf := make([]byte, 10)
- buf[0] = esi.Type
+ buf[0] = uint8(esi.Type)
copy(buf[1:], esi.Value)
return buf, nil
}
+func (esi *EthernetSegmentIdentifier) String() string {
+ s := bytes.NewBuffer(make([]byte, 0, 64))
+ s.WriteString(fmt.Sprintf("%s | ", esi.Type))
+ switch esi.Type {
+ case ESI_LACP:
+ s.WriteString(fmt.Sprintf("system mac %s, ", net.HardwareAddr(esi.Value[:6]).String()))
+ s.WriteString(fmt.Sprintf("port key %d", binary.BigEndian.Uint16(esi.Value[6:8])))
+ case ESI_MSTP:
+ s.WriteString(fmt.Sprintf("bridge mac %s, ", net.HardwareAddr(esi.Value[:6]).String()))
+ s.WriteString(fmt.Sprintf("priority %d", binary.BigEndian.Uint16(esi.Value[6:8])))
+ case ESI_MAC:
+ s.WriteString(fmt.Sprintf("system mac %s, ", net.HardwareAddr(esi.Value[:6]).String()))
+ s.WriteString(fmt.Sprintf("local discriminator %d", esi.Value[6]<<16|esi.Value[7]<<8|esi.Value[8]))
+ case ESI_ROUTERID:
+ s.WriteString(fmt.Sprintf("router id %s, ", net.IP(esi.Value[:4])))
+ s.WriteString(fmt.Sprintf("local discriminator %d", binary.BigEndian.Uint32(esi.Value[4:8])))
+ case ESI_AS:
+ s.WriteString(fmt.Sprintf("as %d:%d, ", binary.BigEndian.Uint16(esi.Value[:2]), binary.BigEndian.Uint16(esi.Value[2:4])))
+ s.WriteString(fmt.Sprintf("local discriminator %d", binary.BigEndian.Uint32(esi.Value[4:8])))
+ default:
+ s.WriteString(fmt.Sprintf("value %s", esi.Value))
+ }
+ return s.String()
+}
+
type EVPNEthernetAutoDiscoveryRoute struct {
RD RouteDistinguisherInterface
- EST EthernetSegmentIdentifier
+ ESI EthernetSegmentIdentifier
ETag uint32
Label uint32
}
@@ -998,7 +1041,7 @@ type EVPNEthernetAutoDiscoveryRoute struct {
func (er *EVPNEthernetAutoDiscoveryRoute) DecodeFromBytes(data []byte) error {
er.RD = getRouteDistinguisher(data)
data = data[er.RD.Len():]
- err := er.EST.DecodeFromBytes(data)
+ err := er.ESI.DecodeFromBytes(data)
if err != nil {
return err
}
@@ -1015,7 +1058,7 @@ func (er *EVPNEthernetAutoDiscoveryRoute) Serialize() ([]byte, error) {
return nil, err
}
- tbuf, err := er.EST.Serialize()
+ tbuf, err := er.ESI.Serialize()
if err != nil {
return nil, err
}
@@ -1034,19 +1077,19 @@ func (er *EVPNEthernetAutoDiscoveryRoute) Serialize() ([]byte, error) {
type EVPNMacIPAdvertisementRoute struct {
RD RouteDistinguisherInterface
- EST EthernetSegmentIdentifier
+ ESI EthernetSegmentIdentifier
ETag uint32
MacAddressLength uint8
- MacAddress []byte
+ MacAddress net.HardwareAddr
IPAddressLength uint8
- IPAddress IPAddrPrefix
+ IPAddress net.IP
Labels []uint32
}
func (er *EVPNMacIPAdvertisementRoute) DecodeFromBytes(data []byte) error {
er.RD = getRouteDistinguisher(data)
data = data[er.RD.Len():]
- err := er.EST.DecodeFromBytes(data)
+ err := er.ESI.DecodeFromBytes(data)
if err != nil {
return err
}
@@ -1054,17 +1097,15 @@ func (er *EVPNMacIPAdvertisementRoute) DecodeFromBytes(data []byte) error {
er.ETag = binary.BigEndian.Uint32(data[0:4])
data = data[4:]
er.MacAddressLength = data[0]
- er.MacAddress = data[1:7]
+ er.MacAddress = net.HardwareAddr(data[1:7])
er.IPAddressLength = data[7]
- data = data[7:]
- if er.IPAddressLength == 32 {
- er.IPAddress.DecodeFromBytes(data[0 : ((er.IPAddressLength)/8)+1])
- } else if er.IPAddressLength == 128 {
- er.IPAddress.DecodeFromBytes(data[0 : ((er.IPAddressLength)/8)+1])
- } else {
+ data = data[8:]
+ if er.IPAddressLength == 32 || er.IPAddressLength == 128 {
+ er.IPAddress = net.IP(data[0:((er.IPAddressLength) / 8)])
+ } else if er.IPAddressLength != 0 {
return fmt.Errorf("Invalid IP address length", er.IPAddressLength)
}
- data = data[(er.IPAddressLength/8)+1:]
+ data = data[(er.IPAddressLength / 8):]
label1 := labelDecode(data)
er.Labels = append(er.Labels, label1)
data = data[3:]
@@ -1082,7 +1123,7 @@ func (er *EVPNMacIPAdvertisementRoute) Serialize() ([]byte, error) {
return nil, err
}
- tbuf, err := er.EST.Serialize()
+ tbuf, err := er.ESI.Serialize()
if err != nil {
return nil, err
}
@@ -1096,14 +1137,14 @@ func (er *EVPNMacIPAdvertisementRoute) Serialize() ([]byte, error) {
copy(tbuf[1:], er.MacAddress)
buf = append(buf, tbuf...)
- tbuf = make([]byte, 1)
-
- if er.IPAddressLength != 0 {
- tbuf, err := er.IPAddress.Serialize()
- if err != nil {
- return nil, err
+ if er.IPAddressLength == 32 || er.IPAddressLength == 128 {
+ buf = append(buf, er.IPAddressLength)
+ if er.IPAddressLength == 32 {
+ er.IPAddress = er.IPAddress.To4()
}
- buf = append(buf, tbuf...)
+ buf = append(buf, []byte(er.IPAddress)...)
+ } else if er.IPAddressLength != 0 {
+ return nil, fmt.Errorf("Invalid IP address length", er.IPAddressLength)
}
for _, l := range er.Labels {
@@ -1118,7 +1159,7 @@ type EVPNMulticastEthernetTagRoute struct {
RD RouteDistinguisherInterface
ETag uint32
IPAddressLength uint8
- IPAddress IPAddrPrefix
+ IPAddress net.IP
}
func (er *EVPNMulticastEthernetTagRoute) DecodeFromBytes(data []byte) error {
@@ -1126,10 +1167,11 @@ func (er *EVPNMulticastEthernetTagRoute) DecodeFromBytes(data []byte) error {
data = data[er.RD.Len():]
er.ETag = binary.BigEndian.Uint32(data[0:4])
er.IPAddressLength = data[4]
- data = data[4:]
- err := er.IPAddress.DecodeFromBytes(data)
- if err != nil {
- return err
+ data = data[5:]
+ if er.IPAddressLength == 32 || er.IPAddressLength == 128 {
+ er.IPAddress = net.IP(data)
+ } else {
+ return fmt.Errorf("Invalid IP address length", er.IPAddressLength)
}
return nil
}
@@ -1142,7 +1184,16 @@ func (er *EVPNMulticastEthernetTagRoute) Serialize() ([]byte, error) {
tbuf := make([]byte, 4)
binary.BigEndian.PutUint32(tbuf, er.ETag)
buf = append(buf, tbuf...)
- tbuf, err = er.IPAddress.Serialize()
+ if er.IPAddressLength == 32 || er.IPAddressLength == 128 {
+ buf = append(buf, er.IPAddressLength)
+ if er.IPAddressLength == 32 {
+ er.IPAddress = er.IPAddress.To4()
+ }
+ buf = append(buf, []byte(er.IPAddress)...)
+ } else {
+ return nil, fmt.Errorf("Invalid IP address length", er.IPAddressLength)
+ }
+
if err != nil {
return nil, err
}
@@ -1152,7 +1203,7 @@ func (er *EVPNMulticastEthernetTagRoute) Serialize() ([]byte, error) {
type EVPNEthernetSegmentRoute struct {
RD RouteDistinguisherInterface
- EST EthernetSegmentIdentifier
+ ESI EthernetSegmentIdentifier
IPAddressLength uint8
IPAddress IPAddrPrefix
}
@@ -1160,7 +1211,7 @@ type EVPNEthernetSegmentRoute struct {
func (er *EVPNEthernetSegmentRoute) DecodeFromBytes(data []byte) error {
er.RD = getRouteDistinguisher(data)
data = data[er.RD.Len():]
- er.EST.DecodeFromBytes(data)
+ er.ESI.DecodeFromBytes(data)
data = data[10:]
er.IPAddressLength = data[0]
err := er.IPAddress.DecodeFromBytes(data[1:])
@@ -1175,7 +1226,7 @@ func (er *EVPNEthernetSegmentRoute) Serialize() ([]byte, error) {
if err != nil {
return nil, err
}
- tbuf, err := er.EST.Serialize()
+ tbuf, err := er.ESI.Serialize()
if err != nil {
return nil, err
}
@@ -1243,8 +1294,9 @@ func (n *EVPNNLRI) DecodeFromBytes(data []byte) error {
func (n *EVPNNLRI) Serialize() ([]byte, error) {
buf := make([]byte, 2)
buf[0] = n.RouteType
- buf[1] = n.Length
tbuf, err := n.RouteTypeData.Serialize()
+ n.Length = uint8(len(tbuf))
+ buf[1] = n.Length
if err != nil {
return nil, err
}