Skip to content
This repository was archived by the owner on Aug 12, 2020. It is now read-only.

Commit 7df94a3

Browse files
committed
add attributes and init nlri
Signed-off-by: Peng Xiao <[email protected]>
1 parent 757f61e commit 7df94a3

File tree

10 files changed

+326
-1
lines changed

10 files changed

+326
-1
lines changed

tox.ini

+2-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ commands = python -m testtools.run \
3939
yabgp.tests.unit.message.attribute.test_community \
4040
yabgp.tests.unit.message.attribute.test_originatorid \
4141
yabgp.tests.unit.message.attribute.test_clusterlist \
42-
yabgp.tests.unit.message.attribute.test_extcommunity
42+
yabgp.tests.unit.message.attribute.test_extcommunity \
43+
yabgp.tests.unit.message.attribute.nlri.test_ipv4_mpls_vpn
4344

4445
[testenv:docs]
4546
deps=

yabgp/common/constants.py

+5
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@
115115
# Unkonw
116116
BGP_EXT_COM_UNKNOW = 0x0000
117117

118+
# route distinguisher type
119+
BGP_ROUTE_DISTINGUISHER_TYPE_0 = 0x0000
120+
BGP_ROUTE_DISTINGUISHER_TYPE_1 = 0x0001
121+
BGP_ROUTE_DISTINGUISHER_TYPE_2 = 0x0001
122+
118123
# NLRI type as define in BGP flow spec RFC
119124
BGPNLRI_FSPEC_DST_PFIX = 1 # RFC 5575
120125
BGPNLRI_FSPEC_SRC_PFIX = 2 # RFC 5575
+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Copyright 2015 Cisco Systems, Inc.
2+
# All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
"""BGP Attribute MP_REACH_NLRI
17+
"""
18+
19+
import struct
20+
21+
from yabgp.message.attribute import Attribute
22+
from yabgp.message.attribute import AttributeFlag
23+
from yabgp.message.attribute import AttributeID
24+
from yabgp.common import afn
25+
from yabgp.common import safn
26+
from yabgp.common import exception as excep
27+
from yabgp.common import constants as bgp_cons
28+
from yabgp.message.attribute.nlri.ipv4_mpls_vpn import IPv4MPLSVPN
29+
30+
31+
class MpReachNLRI(Attribute):
32+
"""
33+
MP_REACH_NLRI (type code 14) is used to carry the set of reachable
34+
destinations together with the next hop information to be used for
35+
forwarding to these destinations (RFC 4760 page 2).
36+
37+
MP_REACH_NLRI coding information
38+
+---------------------------------------------------------+
39+
| Address Family Identifier (2 octets) |
40+
+---------------------------------------------------------+
41+
| Subsequent Address Family Identifier (1 octet) |
42+
+---------------------------------------------------------+
43+
| Length of Next Hop Network Address (1 octet) |
44+
+---------------------------------------------------------+
45+
| Network Address of Next Hop (variable) |
46+
+---------------------------------------------------------+
47+
| Reserved (1 octet) |
48+
+---------------------------------------------------------+
49+
| Network Layer Reachability Information (variable) |
50+
+---------------------------------------------------------+
51+
"""
52+
53+
ID = AttributeID.MP_REACH_NLRI
54+
FLAG = AttributeFlag.OPTIONAL
55+
56+
@classmethod
57+
def parse(cls, value):
58+
59+
try:
60+
afi, safi, nexthop_length = struct.unpack('!HBB', value[0:4])
61+
nexthop_data = value[4:4 + nexthop_length]
62+
nlri_data = value[5 + nexthop_length:]
63+
except Exception:
64+
# error when lenght is wrong
65+
raise excep.UpdateMessageError(
66+
sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN,
67+
data=repr(value))
68+
if afi == afn.AFNUM_INET:
69+
if safi == safn.SAFNUM_LAB_VPNUNICAST:
70+
nlri = IPv4MPLSVPN.parse(nlri_data)
71+
72+
return {
73+
'afi_safi': (afi, safi),
74+
'nexthop': nexthop_data,
75+
'nlri': nlri
76+
}
77+
78+
@classmethod
79+
def construct(cls, value):
80+
pass
+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2015 Cisco Systems, Inc.
2+
# All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
"""BGP Attribute MP_UNREACH_NLRI
17+
"""
18+
19+
from yabgp.message.attribute import Attribute
20+
from yabgp.message.attribute import AttributeFlag
21+
from yabgp.message.attribute import AttributeID
22+
23+
24+
class MpUnReachNLRI(Attribute):
25+
26+
"""
27+
This is an optional non-transitive attribute that can be used for the
28+
purpose of withdrawing multiple unfeasible routes from service.
29+
An UPDATE message that contains the MP_UNREACH_NLRI is not required
30+
to carry any other path attributes.
31+
32+
MP_UNREACH_NLRI coding information
33+
+---------------------------------------------------------+
34+
| Address Family Identifier (2 octets) |
35+
+---------------------------------------------------------+
36+
| Subsequent Address Family Identifier (1 octet) |
37+
+---------------------------------------------------------+
38+
| Withdrawn Routes (variable) |
39+
+---------------------------------------------------------+
40+
"""
41+
42+
ID = AttributeID.MP_UNREACH_NLRI
43+
FLAG = AttributeFlag.OPTIONAL
44+
45+
@classmethod
46+
def parse(cls, value):
47+
pass
48+
49+
@classmethod
50+
def construct(cls, value):
51+
pass

yabgp/message/attribute/nlri/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Copyright 2015 Cisco Systems, Inc.
2+
# All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
"""IPv4 Flowspec NLRI
17+
"""
18+
19+
20+
class IPv4FlowSpec(object):
21+
22+
@classmethod
23+
def parse(cls, value):
24+
"""
25+
parse IPv4 flowspec NLRI
26+
:param value:
27+
:return:
28+
"""
29+
pass
30+
31+
@classmethod
32+
def construct(cls, value):
33+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# coding=utf-8
2+
# Copyright 2015 Cisco Systems, Inc.
3+
# All rights reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6+
# not use this file except in compliance with the License. You may obtain
7+
# a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations
15+
# under the License.
16+
17+
"""IPv4 MPLS VPN NLRI
18+
"""
19+
20+
import struct
21+
import logging
22+
import binascii
23+
24+
import netaddr
25+
26+
from yabgp.common import constants as bgp_cons
27+
28+
LOG = logging.getLogger(__name__)
29+
30+
31+
class IPv4MPLSVPN(object):
32+
33+
"""
34+
IPv4 MPLS VPN NLRI
35+
36+
+---------------------------+
37+
| Length (1 octet) |
38+
+---------------------------+
39+
| Label (3 octet) |
40+
+---------------------------+
41+
|...........................|
42+
+---------------------------+
43+
| Prefix (variable) |
44+
+---------------------------+
45+
a) Length: The Length field indicates the length, in bits, of the address prefix.
46+
b) Label: (24 bits) Carries one or more labels in a stack, although a BGP update
47+
has only one label. This field carries the following parts of the MPLS shim header:
48+
Label Value–—20 Bits
49+
Experimental bits—3 Bits
50+
Bottom of stack bit—1 bit
51+
c) Prefix: different coding way according to different SAFI
52+
Route Distinguisher (8 bytes) plus IPv4 prefix (32 bits) or IPv6 prefix(128 bits)
53+
rd (Route Distinguisher) structure (RFC 4364)
54+
"""
55+
56+
@classmethod
57+
def parse(cls, value):
58+
"""
59+
parse nlri
60+
:param value: the raw hex nlri value
61+
:return: nlri list
62+
"""
63+
nlri_list = []
64+
while value:
65+
nlri_dict = {}
66+
# for python2 and python3
67+
if isinstance(value[0], int):
68+
prefix_bit_len = value[0]
69+
else:
70+
prefix_bit_len = ord(value[0])
71+
if prefix_bit_len % 8 == 0:
72+
prefix_byte_len = int(prefix_bit_len / 8)
73+
else:
74+
prefix_byte_len = int(prefix_bit_len / 8) + 1
75+
76+
label_int = int(binascii.b2a_hex(value[1:4]), 16)
77+
nlri_dict['label'] = (label_int >> 4, label_int & 1)
78+
79+
rd = value[4:12]
80+
rd_type = struct.unpack('!H', rd[0:2])[0]
81+
rd_value = rd[2:8]
82+
nlri_dict['rd_type'] = rd_type
83+
if rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_0:
84+
asn, an = struct.unpack('!HI', rd_value)
85+
nlri_dict['rd'] = '%s:%s' % (asn, an)
86+
elif rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_1:
87+
ip = str(netaddr.IPAddress(struct.unpack('!I', rd_value[0:4])[0]))
88+
an = struct.unpack('!H', rd_value[4:6])[0]
89+
nlri_dict['rd'] = '%s:%s' % (ip, an)
90+
elif rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_2:
91+
asn, an = struct.unpack('!IH', rd_value)
92+
nlri_dict['rd'] = '%s:%s' % (asn, an)
93+
else:
94+
LOG.warning('unknow rd type for nlri, type=%s' % rd_type)
95+
nlri_dict['rd'] = '%s:%s' % (0, 0)
96+
prefix = value[12:prefix_byte_len + 1]
97+
if len(prefix) < 4:
98+
prefix += '\x00' * (4 - len(prefix))
99+
nlri_dict['str'] = str(netaddr.IPAddress(struct.unpack('!I', prefix)[0])) +\
100+
'/%s' % (prefix_bit_len - 88)
101+
value = value[prefix_byte_len + 1:]
102+
nlri_list.append(nlri_dict)
103+
return nlri_list
104+
105+
@classmethod
106+
def contruct(cls, value):
107+
pass
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Copyright 2015 Cisco Systems, Inc.
2+
# All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
"""IPv6 MPLS VPN NLRI
17+
"""

yabgp/tests/unit/message/attribute/nlri/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Copyright 2015 Cisco Systems, Inc.
2+
# All rights reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
""" Test IPv4 MPLS VPN NLRI """
17+
18+
import unittest
19+
20+
from yabgp.message.attribute.nlri.ipv4_mpls_vpn import IPv4MPLSVPN
21+
22+
23+
class TestIPv4MPLSVPN(unittest.TestCase):
24+
25+
def test_parse(self):
26+
nlri_hex = b'\x78\x00\x01\x91\x00\x00\x00\x64\x00\x00\x00\x64\xaa\x00\x00\x00'
27+
self.assertEqual(
28+
[{'label': (25, 1), 'rd': '100:100', 'rd_type': 0, 'str': '170.0.0.0/32'}], IPv4MPLSVPN.parse(nlri_hex))
29+
30+
if __name__ == '__main__':
31+
unittest.main()

0 commit comments

Comments
 (0)