Merge "Fix ipv6 transport failure caused by Ryu 4.9 and above"

This commit is contained in:
Jenkins 2016-12-14 21:44:37 +00:00 committed by Gerrit Code Review
commit 98d3cf24d6
4 changed files with 180 additions and 2 deletions

View File

@ -18,6 +18,8 @@ from oslo_utils import encodeutils
from ryu.services.protocols.bgp import bgpspeaker
from ryu.services.protocols.bgp.rtconf.neighbors import CONNECT_MODE_ACTIVE
from neutron_lib import constants as lib_consts
from neutron_dynamic_routing._i18n import _LE, _LI
from neutron_dynamic_routing.services.bgp.agent.driver import base
from neutron_dynamic_routing.services.bgp.agent.driver import exceptions as bgp_driver_exc # noqa
@ -118,14 +120,22 @@ class RyuBgpDriver(base.BgpDriverBase):
# Validate peer_ip and peer_as.
utils.validate_as_num('remote_as', peer_as)
utils.validate_string(peer_ip)
ip_version = utils.validate_ip_addr(peer_ip)
utils.validate_auth(auth_type, password)
if password is not None:
password = encodeutils.to_utf8(password)
# Notify Ryu about BGP Peer addition
if ip_version == lib_consts.IP_VERSION_4:
enable_ipv4 = True
enable_ipv6 = False
else:
enable_ipv4 = False
enable_ipv6 = True
curr_speaker.neighbor_add(address=peer_ip,
remote_as=peer_as,
enable_ipv4=enable_ipv4,
enable_ipv6=enable_ipv6,
password=password,
connect_mode=CONNECT_MODE_ACTIVE)
LOG.info(_LI('Added BGP Peer %(peer)s for remote_as=%(as)d to '
@ -138,7 +148,7 @@ class RyuBgpDriver(base.BgpDriverBase):
raise bgp_driver_exc.BgpSpeakerNotAdded(local_as=speaker_as,
rtid=self.routerid)
# Validate peer_ip. It must be a string.
utils.validate_string(peer_ip)
utils.validate_ip_addr(peer_ip)
# Notify Ryu about BGP Peer removal
curr_speaker.neighbor_del(address=peer_ip)

View File

@ -13,8 +13,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import netaddr
import six
from neutron_lib import constants as lib_consts
from neutron_dynamic_routing.services.bgp.agent.driver import exceptions as bgp_driver_exc # noqa
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts # noqa
@ -46,6 +49,16 @@ def validate_auth(auth_type, password):
raise bgp_driver_exc.InvaildAuthType(auth_type=auth_type)
def validate_ip_addr(ip_addr):
if netaddr.valid_ipv4(ip_addr):
return lib_consts.IP_VERSION_4
elif netaddr.valid_ipv6(ip_addr):
return lib_consts.IP_VERSION_6
else:
raise bgp_driver_exc.InvalidParamType(param=ip_addr,
param_type='ip-address')
def validate_string(param):
if param is not None:
if not isinstance(param, six.string_types):

View File

@ -35,6 +35,7 @@ FAKE_ROUTER_ID = '1.1.1.1'
# Test variables for BGP Peer
FAKE_PEER_AS = 45678
FAKE_PEER_IP = '2.2.2.5'
FAKE_PEER_IPV6 = '2001:db8::'
FAKE_AUTH_TYPE = 'md5'
FAKE_PEER_PASSWORD = 'awesome'
@ -85,6 +86,8 @@ class TestRyuBgpDriver(base.BaseTestCase):
speaker.neighbor_add.assert_called_once_with(
address=FAKE_PEER_IP,
remote_as=FAKE_PEER_AS,
enable_ipv4=True,
enable_ipv6=False,
password=None,
connect_mode=CONNECT_MODE_ACTIVE)
@ -101,6 +104,8 @@ class TestRyuBgpDriver(base.BaseTestCase):
speaker.neighbor_add.assert_called_once_with(
address=FAKE_PEER_IP,
remote_as=FAKE_PEER_AS,
enable_ipv4=True,
enable_ipv6=False,
password=encodeutils.to_utf8(FAKE_PEER_PASSWORD),
connect_mode=CONNECT_MODE_ACTIVE)
@ -119,9 +124,27 @@ class TestRyuBgpDriver(base.BaseTestCase):
speaker.neighbor_add.assert_called_once_with(
address=FAKE_PEER_IP,
remote_as=FAKE_PEER_AS,
enable_ipv4=True,
enable_ipv6=False,
password=encodeutils.to_utf8(NEW_FAKE_PEER_PASSWORD),
connect_mode=CONNECT_MODE_ACTIVE)
def test_add_bgp_peer_with_ipv6(self):
self.ryu_bgp_driver.add_bgp_speaker(FAKE_LOCAL_AS1)
self.assertEqual(1,
self.ryu_bgp_driver.cache.get_hosted_bgp_speakers_count())
self.ryu_bgp_driver.add_bgp_peer(FAKE_LOCAL_AS1,
FAKE_PEER_IPV6,
FAKE_PEER_AS)
speaker = self.ryu_bgp_driver.cache.get_bgp_speaker(FAKE_LOCAL_AS1)
speaker.neighbor_add.assert_called_once_with(
address=FAKE_PEER_IPV6,
remote_as=FAKE_PEER_AS,
enable_ipv4=False,
enable_ipv6=True,
password=None,
connect_mode=CONNECT_MODE_ACTIVE)
def test_remove_bgp_peer(self):
self.ryu_bgp_driver.add_bgp_speaker(FAKE_LOCAL_AS1)
self.assertEqual(1,
@ -201,6 +224,11 @@ class TestRyuBgpDriver(base.BaseTestCase):
self.ryu_bgp_driver.add_bgp_peer,
FAKE_LOCAL_AS1, FAKE_PEER_IP, FAKE_PEER_AS,
FAKE_AUTH_TYPE, None)
# Test with a invalid ip address
self.assertRaises(bgp_driver_exc.InvalidParamType,
self.ryu_bgp_driver.add_bgp_peer,
FAKE_LOCAL_AS1, '1.2.3.a', FAKE_PEER_AS,
FAKE_AUTH_TYPE, FAKE_PEER_PASSWORD)
def test_add_bgp_peer_with_invalid_asnum_range(self):
self.ryu_bgp_driver.add_bgp_speaker(FAKE_LOCAL_AS1)

View File

@ -13,12 +13,139 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from neutron_lib import constants as lib_consts
from neutron.tests import base
from neutron_dynamic_routing.services.bgp.agent.driver import exceptions as bgp_driver_exc # noqa
from neutron_dynamic_routing.services.bgp.agent.driver import utils as bgp_driver_utils # noqa
from neutron_dynamic_routing.services.bgp.common import constants as bgp_consts # noqa
FAKE_IP = '2.2.2.5'
FAKE_IPV6 = '2001:db8::'
FAKE_LOCAL_AS = 12345
FAKE_RYU_SPEAKER = {}
EXC_INV_PARAMTYPE = "Parameter %(param)s must be of %(param_type)s type."
EXC_INV_PARAMRANGE = "%(param)s must be in %(range)s range."
EXC_PASSWORD_NOTSPEC = "Password not specified for authentication " + \
"type=%(auth_type)s."
EXC_INV_AUTHTYPE = "Authentication type not supported. Requested " + \
"type=%(auth_type)s."
class TestValidateMethod(base.BaseTestCase):
def setUp(self):
super(TestValidateMethod, self).setUp()
def test_validate_as_num_with_valid_as_num(self):
self.assertIsNone(bgp_driver_utils.validate_as_num('local_as',
64512))
def test_validate_as_num_with_string_as_num(self):
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': 'local_as',
'param_type': 'integer'}):
bgp_driver_utils.validate_as_num('local_as', '64512')
def test_validate_as_num_with_invalid_max_range(self):
allowed_range = ('\[' +
str(bgp_consts.MIN_ASNUM) + '-' +
str(bgp_consts.MAX_ASNUM) +
'\]')
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamRange,
EXC_INV_PARAMRANGE % {'param': 'local_as',
'range': allowed_range}):
bgp_driver_utils.validate_as_num('local_as',
bgp_consts.MAX_ASNUM + 1)
def test_validate_as_num_with_invalid_min_range(self):
allowed_range = ('\[' +
str(bgp_consts.MIN_ASNUM) + '-' +
str(bgp_consts.MAX_ASNUM) +
'\]')
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamRange,
EXC_INV_PARAMRANGE % {'param': 'local_as',
'range': allowed_range}):
bgp_driver_utils.validate_as_num('local_as', 0)
def test_validate_auth_with_valid_auth_type(self):
passwords = [None, 'password']
for (auth_type, passwd) in zip(bgp_consts.SUPPORTED_AUTH_TYPES,
passwords):
self.assertIsNone(bgp_driver_utils.validate_auth(auth_type,
passwd))
def test_validate_auth_with_integer_password(self):
auth_type = bgp_consts.SUPPORTED_AUTH_TYPES[1]
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': '12345',
'param_type': 'string'}):
bgp_driver_utils.validate_auth(auth_type, 12345)
def test_validate_auth_with_invalid_auth_type(self):
auth_type = 'abcde'
with self.assertRaisesRegex(
bgp_driver_exc.InvaildAuthType,
EXC_INV_AUTHTYPE % {'auth_type': auth_type}):
bgp_driver_utils.validate_auth(auth_type, 'password')
def test_validate_auth_with_not_none_auth_type_and_none_password(self):
auth_type = bgp_consts.SUPPORTED_AUTH_TYPES[1]
with self.assertRaisesRegex(
bgp_driver_exc.PasswordNotSpecified,
EXC_PASSWORD_NOTSPEC % {'auth_type': auth_type}):
bgp_driver_utils.validate_auth(auth_type, None)
def test_validate_auth_with_none_auth_type_and_not_none_password(self):
auth_type = None
with self.assertRaisesRegex(
bgp_driver_exc.InvaildAuthType,
EXC_INV_AUTHTYPE % {'auth_type': auth_type}):
bgp_driver_utils.validate_auth(auth_type, 'password')
def test_validate_ip_addr_with_ipv4_address(self):
self.assertEqual(lib_consts.IP_VERSION_4,
bgp_driver_utils.validate_ip_addr(FAKE_IP))
def test_validate_ip_addr_with_ipv6_address(self):
self.assertEqual(lib_consts.IP_VERSION_6,
bgp_driver_utils.validate_ip_addr(FAKE_IPV6))
def test_validate_ip_addr_with_integer_ip(self):
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': '12345',
'param_type': 'ip-address'}):
bgp_driver_utils.validate_ip_addr(12345)
def test_validate_ip_addr_with_invalid_ipv4_type(self):
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': '1.2.3.a',
'param_type': 'ip-address'}):
bgp_driver_utils.validate_ip_addr('1.2.3.a')
def test_validate_ip_addr_with_invalid_ipv6_type(self):
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': '2001:db8::ggg',
'param_type': 'ip-address'}):
bgp_driver_utils.validate_ip_addr('2001:db8::ggg')
def test_validate_string_with_string(self):
self.assertIsNone(bgp_driver_utils.validate_string(FAKE_IP))
def test_validate_string_with_integer_param(self):
with self.assertRaisesRegex(
bgp_driver_exc.InvalidParamType,
EXC_INV_PARAMTYPE % {'param': '12345',
'param_type': 'string'}):
bgp_driver_utils.validate_string(12345)
class TestBgpMultiSpeakerCache(base.BaseTestCase):