-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from xiaopeng163/master
add attributes and init nlri
- Loading branch information
Showing
10 changed files
with
326 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
"""BGP Attribute MP_REACH_NLRI | ||
""" | ||
|
||
import struct | ||
|
||
from yabgp.message.attribute import Attribute | ||
from yabgp.message.attribute import AttributeFlag | ||
from yabgp.message.attribute import AttributeID | ||
from yabgp.common import afn | ||
from yabgp.common import safn | ||
from yabgp.common import exception as excep | ||
from yabgp.common import constants as bgp_cons | ||
from yabgp.message.attribute.nlri.ipv4_mpls_vpn import IPv4MPLSVPN | ||
|
||
|
||
class MpReachNLRI(Attribute): | ||
""" | ||
MP_REACH_NLRI (type code 14) is used to carry the set of reachable | ||
destinations together with the next hop information to be used for | ||
forwarding to these destinations (RFC 4760 page 2). | ||
MP_REACH_NLRI coding information | ||
+---------------------------------------------------------+ | ||
| Address Family Identifier (2 octets) | | ||
+---------------------------------------------------------+ | ||
| Subsequent Address Family Identifier (1 octet) | | ||
+---------------------------------------------------------+ | ||
| Length of Next Hop Network Address (1 octet) | | ||
+---------------------------------------------------------+ | ||
| Network Address of Next Hop (variable) | | ||
+---------------------------------------------------------+ | ||
| Reserved (1 octet) | | ||
+---------------------------------------------------------+ | ||
| Network Layer Reachability Information (variable) | | ||
+---------------------------------------------------------+ | ||
""" | ||
|
||
ID = AttributeID.MP_REACH_NLRI | ||
FLAG = AttributeFlag.OPTIONAL | ||
|
||
@classmethod | ||
def parse(cls, value): | ||
|
||
try: | ||
afi, safi, nexthop_length = struct.unpack('!HBB', value[0:4]) | ||
nexthop_data = value[4:4 + nexthop_length] | ||
nlri_data = value[5 + nexthop_length:] | ||
except Exception: | ||
# error when lenght is wrong | ||
raise excep.UpdateMessageError( | ||
sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN, | ||
data=repr(value)) | ||
if afi == afn.AFNUM_INET: | ||
if safi == safn.SAFNUM_LAB_VPNUNICAST: | ||
nlri = IPv4MPLSVPN.parse(nlri_data) | ||
|
||
return { | ||
'afi_safi': (afi, safi), | ||
'nexthop': nexthop_data, | ||
'nlri': nlri | ||
} | ||
|
||
@classmethod | ||
def construct(cls, value): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
"""BGP Attribute MP_UNREACH_NLRI | ||
""" | ||
|
||
from yabgp.message.attribute import Attribute | ||
from yabgp.message.attribute import AttributeFlag | ||
from yabgp.message.attribute import AttributeID | ||
|
||
|
||
class MpUnReachNLRI(Attribute): | ||
|
||
""" | ||
This is an optional non-transitive attribute that can be used for the | ||
purpose of withdrawing multiple unfeasible routes from service. | ||
An UPDATE message that contains the MP_UNREACH_NLRI is not required | ||
to carry any other path attributes. | ||
MP_UNREACH_NLRI coding information | ||
+---------------------------------------------------------+ | ||
| Address Family Identifier (2 octets) | | ||
+---------------------------------------------------------+ | ||
| Subsequent Address Family Identifier (1 octet) | | ||
+---------------------------------------------------------+ | ||
| Withdrawn Routes (variable) | | ||
+---------------------------------------------------------+ | ||
""" | ||
|
||
ID = AttributeID.MP_UNREACH_NLRI | ||
FLAG = AttributeFlag.OPTIONAL | ||
|
||
@classmethod | ||
def parse(cls, value): | ||
pass | ||
|
||
@classmethod | ||
def construct(cls, value): | ||
pass |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
"""IPv4 Flowspec NLRI | ||
""" | ||
|
||
|
||
class IPv4FlowSpec(object): | ||
|
||
@classmethod | ||
def parse(cls, value): | ||
""" | ||
parse IPv4 flowspec NLRI | ||
:param value: | ||
:return: | ||
""" | ||
pass | ||
|
||
@classmethod | ||
def construct(cls, value): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# coding=utf-8 | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
"""IPv4 MPLS VPN NLRI | ||
""" | ||
|
||
import struct | ||
import logging | ||
import binascii | ||
|
||
import netaddr | ||
|
||
from yabgp.common import constants as bgp_cons | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class IPv4MPLSVPN(object): | ||
|
||
""" | ||
IPv4 MPLS VPN NLRI | ||
+---------------------------+ | ||
| Length (1 octet) | | ||
+---------------------------+ | ||
| Label (3 octet) | | ||
+---------------------------+ | ||
|...........................| | ||
+---------------------------+ | ||
| Prefix (variable) | | ||
+---------------------------+ | ||
a) Length: The Length field indicates the length, in bits, of the address prefix. | ||
b) Label: (24 bits) Carries one or more labels in a stack, although a BGP update | ||
has only one label. This field carries the following parts of the MPLS shim header: | ||
Label Value–—20 Bits | ||
Experimental bits—3 Bits | ||
Bottom of stack bit—1 bit | ||
c) Prefix: different coding way according to different SAFI | ||
Route Distinguisher (8 bytes) plus IPv4 prefix (32 bits) or IPv6 prefix(128 bits) | ||
rd (Route Distinguisher) structure (RFC 4364) | ||
""" | ||
|
||
@classmethod | ||
def parse(cls, value): | ||
""" | ||
parse nlri | ||
:param value: the raw hex nlri value | ||
:return: nlri list | ||
""" | ||
nlri_list = [] | ||
while value: | ||
nlri_dict = {} | ||
# for python2 and python3 | ||
if isinstance(value[0], int): | ||
prefix_bit_len = value[0] | ||
else: | ||
prefix_bit_len = ord(value[0]) | ||
if prefix_bit_len % 8 == 0: | ||
prefix_byte_len = int(prefix_bit_len / 8) | ||
else: | ||
prefix_byte_len = int(prefix_bit_len / 8) + 1 | ||
|
||
label_int = int(binascii.b2a_hex(value[1:4]), 16) | ||
nlri_dict['label'] = (label_int >> 4, label_int & 1) | ||
|
||
rd = value[4:12] | ||
rd_type = struct.unpack('!H', rd[0:2])[0] | ||
rd_value = rd[2:8] | ||
nlri_dict['rd_type'] = rd_type | ||
if rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_0: | ||
asn, an = struct.unpack('!HI', rd_value) | ||
nlri_dict['rd'] = '%s:%s' % (asn, an) | ||
elif rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_1: | ||
ip = str(netaddr.IPAddress(struct.unpack('!I', rd_value[0:4])[0])) | ||
an = struct.unpack('!H', rd_value[4:6])[0] | ||
nlri_dict['rd'] = '%s:%s' % (ip, an) | ||
elif rd_type == bgp_cons.BGP_ROUTE_DISTINGUISHER_TYPE_2: | ||
asn, an = struct.unpack('!IH', rd_value) | ||
nlri_dict['rd'] = '%s:%s' % (asn, an) | ||
else: | ||
LOG.warning('unknow rd type for nlri, type=%s' % rd_type) | ||
nlri_dict['rd'] = '%s:%s' % (0, 0) | ||
prefix = value[12:prefix_byte_len + 1] | ||
if len(prefix) < 4: | ||
prefix += '\x00' * (4 - len(prefix)) | ||
nlri_dict['str'] = str(netaddr.IPAddress(struct.unpack('!I', prefix)[0])) +\ | ||
'/%s' % (prefix_bit_len - 88) | ||
value = value[prefix_byte_len + 1:] | ||
nlri_list.append(nlri_dict) | ||
return nlri_list | ||
|
||
@classmethod | ||
def contruct(cls, value): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
"""IPv6 MPLS VPN NLRI | ||
""" |
Empty file.
31 changes: 31 additions & 0 deletions
31
yabgp/tests/unit/message/attribute/nlri/test_ipv4_mpls_vpn.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Copyright 2015 Cisco Systems, Inc. | ||
# All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); you may | ||
# not use this file except in compliance with the License. You may obtain | ||
# a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||
# License for the specific language governing permissions and limitations | ||
# under the License. | ||
|
||
""" Test IPv4 MPLS VPN NLRI """ | ||
|
||
import unittest | ||
|
||
from yabgp.message.attribute.nlri.ipv4_mpls_vpn import IPv4MPLSVPN | ||
|
||
|
||
class TestIPv4MPLSVPN(unittest.TestCase): | ||
|
||
def test_parse(self): | ||
nlri_hex = b'\x78\x00\x01\x91\x00\x00\x00\x64\x00\x00\x00\x64\xaa\x00\x00\x00' | ||
self.assertEqual( | ||
[{'label': (25, 1), 'rd': '100:100', 'rd_type': 0, 'str': '170.0.0.0/32'}], IPv4MPLSVPN.parse(nlri_hex)) | ||
|
||
if __name__ == '__main__': | ||
unittest.main() |