Skip to content

Commit

Permalink
[pytest]: add get_ip_route_info in SonicHost (#1618)
Browse files Browse the repository at this point in the history
get_ip_route_info returns ip route info in the kernel
for a given destination ip

refactor test_default_route to use the new method

Signed-off-by: Guohan Lu <gulv@microsoft.com>
  • Loading branch information
lguohan authored Apr 27, 2020
1 parent e7dab70 commit ce75e16
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 73 deletions.
65 changes: 65 additions & 0 deletions tests/common/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import logging
import os
import re
import ipaddress
from multiprocessing.pool import ThreadPool
from datetime import datetime

Expand Down Expand Up @@ -358,6 +359,7 @@ def get_syncd_docker_names(self):
for npu in range(0,num_npus):
syncd_docker_names.append("syncd{}".format(npu))
return syncd_docker_names

def get_swss_docker_names(self):
swss_docker_names = []
if self.facts["num_npu"] == 1:
Expand Down Expand Up @@ -430,6 +432,69 @@ def no_shutdown(self, ifname):
"""
return self.command("sudo config interface startup {}".format(ifname))

def get_ip_route_info(self, dstip):
"""
@summary: return route information for a destionation IP
@param dstip: destination IP (either ipv4 or ipv6)
============ 4.19 kernel ==============
admin@vlab-01:~$ ip route list match 0.0.0.0
default proto bgp src 10.1.0.32 metric 20
nexthop via 10.0.0.57 dev PortChannel0001 weight 1
nexthop via 10.0.0.59 dev PortChannel0002 weight 1
nexthop via 10.0.0.61 dev PortChannel0003 weight 1
nexthop via 10.0.0.63 dev PortChannel0004 weight 1
admin@vlab-01:~$ ip -6 route list match ::
default proto bgp src fc00:1::32 metric 20
nexthop via fc00::72 dev PortChannel0001 weight 1
nexthop via fc00::76 dev PortChannel0002 weight 1
nexthop via fc00::7a dev PortChannel0003 weight 1
nexthop via fc00::7e dev PortChannel0004 weight 1 pref medium
============ 4.9 kernel ===============
admin@vlab-01:~$ ip route list match 0.0.0.0
default proto 186 src 10.1.0.32 metric 20
nexthop via 10.0.0.57 dev PortChannel0001 weight 1
nexthop via 10.0.0.59 dev PortChannel0002 weight 1
nexthop via 10.0.0.61 dev PortChannel0003 weight 1
nexthop via 10.0.0.63 dev PortChannel0004 weight 1
admin@vlab-01:~$ ip -6 route list match ::
default via fc00::72 dev PortChannel0001 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::76 dev PortChannel0002 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7a dev PortChannel0003 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7e dev PortChannel0004 proto 186 src fc00:1::32 metric 20 pref medium
"""

if dstip.version == 4:
rt = self.command("ip route list match {}".format(dstip))['stdout_lines']
else:
rt = self.command("ip -6 route list match {}".format(dstip))['stdout_lines']

logging.info("route raw info for {}: {}".format(dstip, rt))

rtinfo = {'set_src': None, 'nexthops': [] }

# parse set_src
m = re.match(r"^default proto (bgp|186) src (\S+)", rt[0])
m1 = re.match(r"^default via (\S+) dev (\S+) proto 186 src (\S+)", rt[0])
if m:
rtinfo['set_src'] = ipaddress.ip_address(m.group(2))
elif m1:
rtinfo['set_src'] = ipaddress.ip_address(m.group(3))

# parse nexthops
for l in rt:
m = re.search(r"(default|nexthop) via (\S+) dev (\S+)", l)
if m:
rtinfo['nexthops'].append((ipaddress.ip_address(m.group(2)), m.group(3)))

logging.info("route parsed info for {}: {}".format(dstip, rtinfo))

return rtinfo

class EosHost(AnsibleHostBase):
"""
Expand Down
90 changes: 17 additions & 73 deletions tests/route/test_default_route.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,13 @@
import ipaddress
import re
import pytest
import logging
from common.helpers.assertions import pytest_assert

logger = logging.getLogger(__name__)

def test_default_route_set_src(duthost):
"""check if ipv4 and ipv6 default src address match Loopback0 address
admin@vlab-01:~$ ip route list match 0.0.0.0
default proto bgp src 10.1.0.32 metric 20
nexthop via 10.0.0.57 dev PortChannel0001 weight 1
nexthop via 10.0.0.59 dev PortChannel0002 weight 1
nexthop via 10.0.0.61 dev PortChannel0003 weight 1
nexthop via 10.0.0.63 dev PortChannel0004 weight 1
admin@vlab-01:~$ ip -6 route list match ::
default proto bgp src fc00:1::32 metric 20
nexthop via fc00::72 dev PortChannel0001 weight 1
nexthop via fc00::76 dev PortChannel0002 weight 1
nexthop via fc00::7a dev PortChannel0003 weight 1
nexthop via fc00::7e dev PortChannel0004 weight 1 pref medium
"""
check if ipv4 and ipv6 default src address match Loopback0 address
============ 4.9 kernel ===============
admin@vlab-01:~$ ip route list match 0.0.0.0
default proto 186 src 10.1.0.32 metric 20
nexthop via 10.0.0.57 dev PortChannel0001 weight 1
nexthop via 10.0.0.59 dev PortChannel0002 weight 1
nexthop via 10.0.0.61 dev PortChannel0003 weight 1
nexthop via 10.0.0.63 dev PortChannel0004 weight 1
admin@vlab-01:~$ ip -6 route list match ::
default via fc00::72 dev PortChannel0001 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::76 dev PortChannel0002 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7a dev PortChannel0003 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7e dev PortChannel0004 proto 186 src fc00:1::32 metric 20 pref medium
"""

config_facts = duthost.config_facts(host=duthost.hostname, source="running")['ansible_facts']
Expand All @@ -55,53 +28,24 @@ def test_default_route_set_src(duthost):
pytest_assert(lo_ipv4, "cannot find ipv4 Loopback0 address")
pytest_assert(lo_ipv6, "cannot find ipv6 Loopback0 address")

rt = duthost.command("ip route list match 0.0.0.0")['stdout_lines']
m = re.match(r"^default proto (bgp|186) src (\S+)", rt[0])
if m:
pytest_assert(ipaddress.ip_address(m.group(2)) == lo_ipv4.ip, \
"default route set src to wrong IP {} != {}".format(m.group(1), lo_ipv4.ip))
else:
pytest.fail("default route do not have set src. {}".format(rt))
rtinfo = duthost.get_ip_route_info(ipaddress.ip_address(u"0.0.0.0"))
pytest_assert(rtinfo['set_src'], "default route do not have set src. {}".format(rtinfo))
pytest_assert(rtinfo['set_src'] == lo_ipv4.ip, \
"default route set src to wrong IP {} != {}".format(rtinfo['set_src'], lo_ipv4.ip))

rt = duthost.command("ip -6 route list match ::")['stdout_lines']
m = re.match(r"^default proto bgp src (\S+)", rt[0])
m1 = re.match(r"default via (\S+) dev (\S+) proto 186 src (\S+)", rt[0])
if m:
pytest_assert(ipaddress.ip_address(m.group(1)) == lo_ipv6.ip, \
"default route set src to wrong IP {} != {}".format(m.group(1), lo_ipv6.ip))
elif m1:
pytest_assert(ipaddress.ip_address(m1.group(3)) == lo_ipv6.ip, \
"default route set src to wrong IP {} != {}".format(m1.group(3), lo_ipv6.ip))
else:
pytest.fail("default route do not have set src. {}".format(rt))
rtinfo = duthost.get_ip_route_info(ipaddress.ip_address(u"::"))
pytest_assert(rtinfo['set_src'], "default v6 route do not have set src. {}".format(rtinfo))
pytest_assert(rtinfo['set_src'] == lo_ipv6.ip, \
"default v6 route set src to wrong IP {} != {}".format(rtinfo['set_src'], lo_ipv6.ip))

def test_default_ipv6_route_next_hop_global_address(duthost):
"""check if ipv6 default route nexthop address uses global address
admin@vlab-01:~$ ip -6 route list match ::
default proto bgp src fc00:1::32 metric 20
nexthop via fc00::72 dev PortChannel0001 weight 1
nexthop via fc00::76 dev PortChannel0002 weight 1
nexthop via fc00::7a dev PortChannel0003 weight 1
nexthop via fc00::7e dev PortChannel0004 weight 1 pref medium
============ 4.9 kernel ===============
admin@vlab-01:~$ ip -6 route list match ::
default via fc00::72 dev PortChannel0001 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::76 dev PortChannel0002 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7a dev PortChannel0003 proto 186 src fc00:1::32 metric 20 pref medium
default via fc00::7e dev PortChannel0004 proto 186 src fc00:1::32 metric 20 pref medium
"""
check if ipv6 default route nexthop address uses global address
rt = duthost.command("ip -6 route list match ::")['stdout_lines']
logger.info("default ipv6 route {}".format(rt))
found_nexthop_via = False
for l in rt:
m = re.search(r"(default|nexthop) via (\S+)", l)
if m:
found_nexthop_via = True
pytest_assert(not ipaddress.ip_address(m.group(2)).is_link_local, \
"use link local address {} for nexthop".format(m.group(2)))
"""

pytest_assert(found_nexthop_via, "cannot find ipv6 nexthop for default route {}".format(rt))
rtinfo = duthost.get_ip_route_info(ipaddress.ip_address(u"::"))
pytest_assert(rtinfo['nexthops'] > 0, "cannot find ipv6 nexthop for default route")
for nh in rtinfo['nexthops']:
pytest_assert(not nh[0].is_link_local, \
"use link local address {} for nexthop".format(nh[0]))

0 comments on commit ce75e16

Please sign in to comment.