Skip to content

Commit

Permalink
mp reach nlri and unreach nlri support ipv6 unicast
Browse files Browse the repository at this point in the history
Signed-off-by: Peng Xiao <xiaoquwl@gmail.com>
  • Loading branch information
xiaopeng163 committed Dec 28, 2015
1 parent f167110 commit be459d2
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 4 deletions.
17 changes: 17 additions & 0 deletions yabgp/message/attribute/mpreachnlri.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,23 @@ def construct(cls, value):
raise excep.ConstructAttributeFailed(
reason='unsupport this sub address family',
data=value)

# ipv6 unicast
elif afi == afn.AFNUM_INET6:
if safi == safn.SAFNUM_UNICAST:
nexthop_len = 16
nexthop_bin = netaddr.IPAddress(value['nexthop']).packed
if value.get('linklocal_nexthop'):
nexthop_len *= 2
nexthop_bin += netaddr.IPAddress(value['linklocal_nexthop']).packed

nlri_bin = IPv6Unicast.construct(nlri_list=value['nlri'])

attr_value = struct.pack('!H', afi) + struct.pack('!B', safi) + struct.pack('!B', nexthop_len) + \
nexthop_bin + b'\x00' + nlri_bin
return struct.pack('!B', cls.FLAG) + struct.pack('!B', cls.ID)\
+ struct.pack('!B', len(attr_value)) + attr_value

else:
raise excep.ConstructAttributeFailed(
reason='unsupport this sub address family',
Expand Down
26 changes: 22 additions & 4 deletions yabgp/message/attribute/mpunreachnlri.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from yabgp.message.attribute import AttributeFlag
from yabgp.message.attribute import AttributeID
from yabgp.message.attribute.nlri.ipv4_flowspec import IPv4FlowSpec
from yabgp.message.attribute.nlri.ipv6_unicast import IPv6Unicast
from yabgp.common import afn
from yabgp.common import safn
from yabgp.common import exception as excep
Expand Down Expand Up @@ -57,18 +58,26 @@ def parse(cls, value):
raise excep.UpdateMessageError(sub_error=bgp_cons.ERR_MSG_UPDATE_ATTR_LEN,
data='')

nlri = value[3:]
nlri_bin = value[3:]

# for IPv4
if afi == afn.AFNUM_INET:
# BGP flow spec
if safi == safn.SAFNUM_FSPEC_RULE:
return IPv4FlowSpec().parse(value=nlri)
return IPv4FlowSpec().parse(value=nlri_bin)
else:
return {'afi_safi': (afn.AFNUM_INET, safi),
'withdraw': repr(nlri)}
'withdraw': repr(nlri_bin)}
# for ipv6
elif afi == afn.AFNUM_INET6:
# for ipv6 unicast
if safi == safn.SAFNUM_UNICAST:
return dict(afi_safi=(afi, safi), withdraw=IPv6Unicast.parse(nlri_data=nlri_bin))
else:
return dict(afi_safi=(afi, safi), withdraw=repr(nlri_bin))

return dict(afi_safi=(afi, safi), withdraw=nlri)
else:
return dict(afi_safi=(afi, safi), withdraw=repr(nlri_bin))

@classmethod
def construct(cls, value):
Expand Down Expand Up @@ -103,6 +112,15 @@ def construct(cls, value):
raise excep.ConstructAttributeFailed(
reason='unsupport this sub address family',
data=value)
elif afi == afn.AFNUM_INET6:
if safi == safn.SAFNUM_UNICAST:
nlri = IPv6Unicast.construct(nlri_list=value['withdraw'])
if nlri:
attr_value = struct.pack('!H', afi) + struct.pack('!B', safi) + nlri
return struct.pack('!B', cls.FLAG) + struct.pack('!B', cls.ID) \
+ struct.pack('!B', len(attr_value)) + attr_value
else:
return None
else:
raise excep.ConstructAttributeFailed(
reason='unsupport this sub address family',
Expand Down
16 changes: 16 additions & 0 deletions yabgp/tests/unit/message/attribute/test_mpreachnlri.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,21 @@ def test_ipv6_unicast_with_linklocal_nexthop(self):
'nexthop': '2001:db8::2',
'nlri': ['::2001:db8:2:2/64', '::2001:db8:2:1/64', '::2001:db8:2:0/64']}
self.assertEqual(data_hoped, MpReachNLRI.parse(data_bin))

def test_ipv6_unicast_construct(self):
data_parsed = {
'afi_safi': (2, 1),
'nexthop': '2001:3232::1',
'nlri': ['2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127']}
self.assertEqual(data_parsed, MpReachNLRI.parse(MpReachNLRI.construct(data_parsed)[3:]))

def test_ipv6_unicast_with_locallink_nexthop_construct(self):
data_hoped = {
'afi_safi': (2, 1),
'linklocal_nexthop': 'fe80::c002:bff:fe7e:0',
'nexthop': '2001:db8::2',
'nlri': ['::2001:db8:2:2/64', '::2001:db8:2:1/64', '::2001:db8:2:0/64']}
self.assertEqual(data_hoped, MpReachNLRI.parse(MpReachNLRI.construct(data_hoped)[3:]))

if __name__ == '__main__':
unittest.main()
42 changes: 42 additions & 0 deletions yabgp/tests/unit/message/attribute/test_mpunreachnlri.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# 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.

""" Unittest for MPUnReach NLRI"""

import unittest

from yabgp.message.attribute.mpunreachnlri import MpUnReachNLRI


class TestMpUnReachNLRI(unittest.TestCase):

def setUp(self):

self.maxDiff = None

def test_ipv6_unicast_parse(self):

data_bin = b"\x00\x02\x01\x80\x20\x01\x48\x37\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20"
data_hoped = {'afi_safi': (2, 1), 'withdraw': ['2001:4837::20/128']}
self.assertEqual(data_hoped, MpUnReachNLRI.parse(data_bin))

def test_ipv6_unicast_construct(self):
nlri_dict = {
'afi_safi': (2, 1),
'withdraw': ['2001:3232::1/128', '::2001:3232:1:0/64', '2001:4837:1632::2/127']}
self.assertEqual(nlri_dict, MpUnReachNLRI.parse(MpUnReachNLRI.construct(nlri_dict)[3:]))

if __name__ == '__main__':
unittest.main()

0 comments on commit be459d2

Please sign in to comment.