diff options
author | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-03-12 02:43:06 +0900 |
---|---|---|
committer | FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> | 2015-03-12 02:43:06 +0900 |
commit | 35924fdd5c411301d9d0122308e20b138b665aef (patch) | |
tree | 252eaea5c76d248aac2ced940abf25f5c3120580 /packet | |
parent | 208a6bcebea6008636bda49c5569dc2ba1d4f3f9 (diff) |
packet: add EVPN NLRI parser and serializer
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Diffstat (limited to 'packet')
-rw-r--r-- | packet/bgp.go | 297 |
1 files changed, 297 insertions, 0 deletions
diff --git a/packet/bgp.go b/packet/bgp.go index 1b80e543..db7ff88a 100644 --- a/packet/bgp.go +++ b/packet/bgp.go @@ -705,6 +705,16 @@ func getRouteDistinguisher(data []byte) RouteDistinguisherInterface { return rd } +func labelDecode(data []byte) uint32 { + return uint32(data[0]<<16 | data[1]<<8 | data[2]) +} + +func labelSerialize(label uint32, buf []byte) { + buf[0] = byte((label >> 16) & 0xff) + buf[1] = byte((label >> 8) & 0xff) + buf[2] = byte(label & 0xff) +} + type Label struct { Labels []uint32 } @@ -955,6 +965,293 @@ func (n *RouteTargetMembershipNLRI) String() string { return fmt.Sprintf("%d:%s/%d", n.AS, n.RouteTarget.String(), n.Len()*8) } +type EthernetSegmentIdentifier struct { + Type uint8 + Value []byte +} + +func (esi *EthernetSegmentIdentifier) DecodeFromBytes(data []byte) error { + esi.Type = data[0] + esi.Value = data[1:10] + return nil +} + +func (esi *EthernetSegmentIdentifier) Serialize() ([]byte, error) { + buf := make([]byte, 10) + buf[0] = esi.Type + copy(buf[1:], esi.Value) + return buf, nil +} + +type EVPNEthernetAutoDiscoveryRoute struct { + RD RouteDistinguisherInterface + EST EthernetSegmentIdentifier + ETag uint32 + Label uint32 +} + +func (er *EVPNEthernetAutoDiscoveryRoute) DecodeFromBytes(data []byte) error { + er.RD = getRouteDistinguisher(data) + data = data[er.RD.Len():] + err := er.EST.DecodeFromBytes(data) + if err != nil { + return err + } + data = data[10:] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + data = data[4:] + er.Label = labelDecode(data) + return nil +} + +func (er *EVPNEthernetAutoDiscoveryRoute) Serialize() ([]byte, error) { + buf, err := er.RD.Serialize() + if err != nil { + return nil, err + } + + tbuf, err := er.EST.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + tbuf = make([]byte, 4) + binary.BigEndian.PutUint32(tbuf, er.ETag) + buf = append(buf, tbuf...) + + tbuf = make([]byte, 3) + labelSerialize(er.Label, tbuf) + buf = append(buf, tbuf...) + + return buf, nil +} + +type EVPNMacIPAdvertisementRoute struct { + EST EthernetSegmentIdentifier + ETag uint32 + MacAddressLength uint8 + MacAddress []byte + IPAddressLength uint8 + IPAddress IPAddrPrefix + Labels []uint32 +} + +func (er *EVPNMacIPAdvertisementRoute) DecodeFromBytes(data []byte) error { + err := er.EST.DecodeFromBytes(data) + if err != nil { + return err + } + + data = data[10:] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + data = data[4:] + + er.MacAddressLength = data[0] + er.MacAddress = data[1:7] + er.IPAddressLength = data[8] + data = data[9:] + switch er.IPAddressLength { + case 0: + // do nothing + case 4: + er.IPAddress.DecodeFromBytes(data) + case 6: + er.IPAddress.DecodeFromBytes(data) + default: + return fmt.Errorf("Invalid IP address length", er.IPAddressLength) + } + data = data[er.IPAddressLength:] + label1 := labelDecode(data) + er.Labels = append(er.Labels, label1) + data = data[3:] + if len(data) == 3 { + label2 := labelDecode(data) + er.Labels = append(er.Labels, label2) + + } + return nil +} + +func (er *EVPNMacIPAdvertisementRoute) Serialize() ([]byte, error) { + buf, err := er.EST.Serialize() + if err != nil { + return nil, err + } + + tbuf := make([]byte, 4) + binary.BigEndian.PutUint32(tbuf, er.ETag) + buf = append(buf, tbuf...) + + tbuf = make([]byte, 7) + tbuf[0] = er.MacAddressLength + copy(tbuf[1:], er.MacAddress) + buf = append(buf, tbuf...) + + tbuf = make([]byte, 1) + tbuf[0] = er.IPAddressLength + buf = append(buf, tbuf...) + + if er.IPAddressLength != 0 { + tbuf, err := er.IPAddress.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + } + + for _, l := range er.Labels { + tbuf = make([]byte, 3) + labelSerialize(l, tbuf) + buf = append(buf, tbuf...) + } + return buf, nil +} + +type EVPNMulticastEthernetTagRoute struct { + RD RouteDistinguisherInterface + ETag uint32 + IPAddressLength uint8 + IPAddress IPAddrPrefix +} + +func (er *EVPNMulticastEthernetTagRoute) DecodeFromBytes(data []byte) error { + er.RD = getRouteDistinguisher(data) + data = data[er.RD.Len():] + er.ETag = binary.BigEndian.Uint32(data[0:4]) + er.IPAddressLength = data[4] + data = data[5:] + err := er.IPAddress.DecodeFromBytes(data) + if err != nil { + return err + } + return nil +} + +func (er *EVPNMulticastEthernetTagRoute) Serialize() ([]byte, error) { + buf, err := er.RD.Serialize() + if err != nil { + return nil, err + } + tbuf := make([]byte, 5) + binary.BigEndian.PutUint32(tbuf, er.ETag) + tbuf[4] = er.IPAddressLength + buf = append(buf, tbuf...) + + tbuf, err = er.IPAddress.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + return buf, nil +} + +type EVPNEthernetSegmentRoute struct { + RD RouteDistinguisherInterface + EST EthernetSegmentIdentifier + IPAddressLength uint8 + IPAddress IPAddrPrefix +} + +func (er *EVPNEthernetSegmentRoute) DecodeFromBytes(data []byte) error { + er.RD = getRouteDistinguisher(data) + data = data[er.RD.Len():] + er.EST.DecodeFromBytes(data) + data = data[10:] + er.IPAddressLength = data[0] + err := er.IPAddress.DecodeFromBytes(data[1:]) + if err != nil { + return err + } + return nil +} + +func (er *EVPNEthernetSegmentRoute) Serialize() ([]byte, error) { + buf, err := er.RD.Serialize() + if err != nil { + return nil, err + } + tbuf, err := er.EST.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + tbuf = make([]byte, 1) + tbuf[0] = er.IPAddressLength + buf = append(buf, tbuf...) + + tbuf, err = er.IPAddress.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + + return buf, nil +} + +type EVPNRouteTypeInterface interface { + DecodeFromBytes([]byte) error + Serialize() ([]byte, error) +} + +func getEVPNRouteType(t uint8) (EVPNRouteTypeInterface, error) { + switch t { + case EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY: + return &EVPNEthernetAutoDiscoveryRoute{}, nil + case EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT: + return &EVPNMacIPAdvertisementRoute{}, nil + case EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG: + return &EVPNMulticastEthernetTagRoute{}, nil + case EVPN_ETHERNET_SEGMENT_ROUTE: + return &EVPNEthernetSegmentRoute{}, nil + } + return nil, fmt.Errorf("Unknown EVPN Route type", t) +} + +const ( + EVPN_ROUTE_TYPE_ETHERNET_AUTO_DISCOVERY = 1 + EVPN_ROUTE_TYPE_MAC_IP_ADVERTISEMENT = 2 + EVPN_INCLUSIVE_MULTICAST_ETHERNET_TAG = 3 + EVPN_ETHERNET_SEGMENT_ROUTE = 4 +) + +type EVPNNLRI struct { + RouteType uint8 + Length uint8 + RouteTypeData EVPNRouteTypeInterface +} + +func (n *EVPNNLRI) DecodeFromBytes(data []byte) error { + if len(data) < 2 { + return fmt.Errorf("Not all EVPNNLRI bytes available") + } + n.RouteType = data[0] + n.Length = data[1] + data = data[2:] + if len(data) < int(n.Length) { + return fmt.Errorf("Not all EVPNNLRI Route type bytes available") + } + r, err := getEVPNRouteType(n.RouteType) + if err != nil { + return err + } + return r.DecodeFromBytes(data) +} + +func (n *EVPNNLRI) Serialize() ([]byte, error) { + buf := make([]byte, 2) + buf[0] = n.RouteType + buf[1] = n.Length + tbuf, err := n.RouteTypeData.Serialize() + if err != nil { + return nil, err + } + buf = append(buf, tbuf...) + return buf, nil +} + func AfiSafiToRouteFamily(afi uint16, safi uint8) RouteFamily { return RouteFamily(int(afi)<<16 | int(safi)) } |