Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace deprecated and obsoleted IPDB with NDB #758

Closed
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
3a22664
Replace deprecated `IPDB` with `NDB`
gab-arrobo Feb 5, 2024
16cc53a
Merge branch 'master' into replace-deprecated-ipdb
gab-arrobo Feb 7, 2024
5664b7b
Update test file
gab-arrobo Feb 7, 2024
1a4a15f
Apply suggestions from code review
gab-arrobo Feb 7, 2024
526d168
Use get method
gab-arrobo Feb 7, 2024
e656a2e
Merge branch 'master' into replace-deprecated-ipdb
gab-arrobo Feb 7, 2024
7c696da
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Feb 7, 2024
16f68db
No need to register callbacks because NDB continuously monitors the s…
gab-arrobo Feb 7, 2024
55de595
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Feb 15, 2024
2e05e4f
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Feb 22, 2024
094e687
Partially address issue with registrer_handler
gab-arrobo Feb 22, 2024
56b95ba
Update route control script. Still need to address issue with `core` …
gab-arrobo Feb 22, 2024
0982fb7
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Feb 27, 2024
25b1a1d
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 5, 2024
1da2ecd
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 6, 2024
a390989
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 8, 2024
824ed04
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 9, 2024
6b7b490
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 11, 2024
33c5cbd
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 21, 2024
5ff4806
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Mar 26, 2024
011dd93
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Apr 11, 2024
a31d6fa
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Apr 24, 2024
68e9893
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Apr 26, 2024
690531e
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo May 2, 2024
748412e
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo May 28, 2024
c035ec0
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Jun 4, 2024
5cde3ce
Merge branch 'omec-project:master' into replace-deprecated-ipdb
gab-arrobo Jun 12, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 18 additions & 29 deletions conf/route_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from typing import Dict, List, Optional, Tuple

from pybess.bess import *
from pyroute2 import IPDB, IPRoute
from pyroute2 import NDB, IPRoute
from scapy.all import ICMP, IP, send

LOG_FORMAT = "%(asctime)s %(levelname)s %(message)s"
Expand Down Expand Up @@ -308,7 +308,7 @@ class RouteController:
def __init__(
self,
bess_controller: BessController,
ipdb: IPDB,
ndb: NDB,
ipr: IPRoute,
interfaces: List[str],
):
Expand All @@ -319,7 +319,7 @@ def __init__(
bess_controller (BessController):
Controller for BESS (Berkeley Extensible Software Switch).
route_parser (RouteEntryParser): Parser for route entries.
ipdb (IPDB): IP database to manage IP configurations.
ndb (NDB): database to manage Network configurations.
ipr (IPRoute): IP routing control object.

Attributes:
Expand All @@ -336,7 +336,7 @@ def __init__(

self._lock = Lock()

self._ipdb = ipdb
self._ndb = ndb
self._ipr = ipr
self._bess_controller = bess_controller
self._ping_missing_thread = Thread(
Expand All @@ -345,13 +345,6 @@ def __init__(
self._event_callback = None
self._interfaces = interfaces

def register_callbacks(self) -> None:
"""Register callback function."""
logger.info("Registering netlink event listener callback...")
self._event_callback = self._ipdb.register_callback(
self._netlink_event_listener
)

def start_pinging_missing_entries(self) -> None:
"""Starts a new thread for ping missing entries."""
if not self._ping_missing_thread or not self._ping_missing_thread.is_alive():
Expand All @@ -373,7 +366,7 @@ def add_new_route_entry(self, route_entry: RouteEntry) -> None:
Args:
route_entry (RouteEntry): The route entry.
"""
if not (next_hop_mac := fetch_mac(self._ipdb, route_entry.next_hop_ip)):
if not (next_hop_mac := fetch_mac(self._ndb, route_entry.next_hop_ip)):
logger.info(
"mac address of the next hop %s is not stored in ARP table. Probing...",
route_entry.next_hop_ip,
Expand Down Expand Up @@ -603,12 +596,12 @@ def _get_gate_idx(self, route_entry: RouteEntry, module_name: str) -> int:
return self._module_gate_count_cache[module_name]

def _netlink_event_listener(
self, ipdb: IPDB, netlink_message: dict, action: str
self, ndb: NDB, netlink_message: dict, action: str
) -> None:
"""Listens for netlink events and handles them.

Args:
ipdb (IPDB): The IPDB object.
ndb (NDB): The NDB object.
netlink_message (dict): The netlink message.
action (str): The action.
"""
Expand All @@ -627,10 +620,8 @@ def _netlink_event_listener(
self.add_unresolved_new_neighbor(netlink_message)

def cleanup(self, number: int) -> None:
"""Unregisters the netlink event listener callback and exits."""
"""Exits execution."""
logger.info("Received: %i Exiting", number)
self._ipdb.unregister_callback(self._event_callback)
logger.info("Unregistered netlink event listener callback")
sys.exit()

def reconfigure(self, number: int) -> None:
Expand Down Expand Up @@ -667,7 +658,7 @@ def _parse_route_entry_msg(self, route_entry: dict) -> Optional[RouteEntry]:
if not attr_dict.get(KEY_INTERFACE):
return None
interface_index = int(attr_dict.get(KEY_INTERFACE))
interface = self._ipdb.interfaces[interface_index].ifname
interface = self._ndb.interfaces[interface_index].get("ifname")
if interface not in self._interfaces:
return None

Expand Down Expand Up @@ -736,26 +727,25 @@ def send_ping(neighbor_ip):
send(IP(dst=neighbor_ip) / ICMP())


def fetch_mac(ipdb: IPDB, target_ip: str) -> Optional[str]:
"""Fetches the MAC address of the target IP from the ARP table using IPDB.
def fetch_mac(ndb: NDB, target_ip: str) -> Optional[str]:
"""Fetches the MAC address of the target IP from the ARP table using NDB.

Args:
ipdb (IPDB): The IPDB object.
ndb (NDB): The NDB object.
target_ip (str): The target IP address.

Returns:
Optional[str]: The MAC address of the target IP.
"""
neighbors = ipdb.nl.get_neighbours(dst=target_ip)
neighbors = ndb.neighbours.dump()
for neighbor in neighbors:
attrs = dict(neighbor["attrs"])
if attrs.get(KEY_NETWORK_LAYER_DEST_ADDR, "") == target_ip:
if neighbor["dst"] == target_ip:
logger.info(
"Mac address found for %s, Mac: %s",
target_ip,
attrs.get(KEY_LINK_LAYER_ADDRESS, ""),
neighbor["lladdr"],
)
return attrs.get(KEY_LINK_LAYER_ADDRESS, "")
return neighbor["lladdr"]
logger.info("Mac address not found for %s", target_ip)
return None

Expand Down Expand Up @@ -800,16 +790,15 @@ def register_signal_handlers(route_controller: RouteController) -> None:
if __name__ == "__main__":
interface_arg, ip_arg, port_arg = parse_args()
ipr = IPRoute()
ipdb = IPDB()
ndb = NDB()
bess_controller = BessController(ip_arg, port_arg)
route_controller = RouteController(
bess_controller=bess_controller,
ipdb=ipdb,
ndb=ndb,
ipr=ipr,
interfaces=interface_arg,
)
route_controller.bootstrap_routes()
route_controller.register_callbacks()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This callback was the way that routectl was notified that a new mac address was added to the arp table so that it could configure BESS. I do not see a replacement for this.

When routectl starts, it will look for the mac address of the access gateway and core gateway, and if they are not present, it is sending pings out in the background. The mac address will be added to the arp table in the background. We need to either get notified of the change, or do some kind of polling.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, that is because the way IPDB works. However, with NDB, that should not be needed as indicated here (also below):

The goal of NDB is to provide an easy access to RTNL info and entities via Python objects, like
pyroute2.ndb.objects.interface (see also: [Network interfaces]
(https://docs.pyroute2.org/ndb_interfaces.html#ndbinterfaces)), pyroute2.ndb.objects.route (see also: Routes
management
) etc. These objects do not only reflect the
system state for the time of their instantiation, but continuously monitor the system for relevant updates. The
monitoring is done via netlink notifications, thus no polling.

Moreover, as indicated here, NDB does NOT have a register_callback method and when I was trying to use the method indicated in the issue (ndb.register_handler()), I got an error. I am currently running some tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But will we react to those changes even if they are monitored by NDB?
And if it is the case that we don't need to register callbacks anymore then we probably could remove _netlink_event_listener.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But will we react to those changes even if they are monitored by NDB? And if it is the case that we don't need to register callbacks anymore then we probably could remove _netlink_event_listener.

It looks like the register_handler() is needed because when running the UPF as part of AiaB, the E2E fails. I am planning to add the register_handler() and run some tests.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When using regsiter_handler(), I get an error message saying "AttributeError: 'NDB' object has no attribute 'register_handler'"

Click me to see routectl logs

$ kubectl -n omec logs upf-0 -c routectl
2024-02-08 08:06:09,186 INFO Connected to BESS daemon
2024-02-08 08:06:09,197 INFO Mac address found for 192.168.250.1, Mac: 3e:8d:e3:da:cb:3e
2024-02-08 08:06:09,201 INFO Route entry 0.0.0.0/0 added to coreRoutes
2024-02-08 08:06:09,205 INFO Neighbor entry does not exist, creating modules.
2024-02-08 08:06:09,208 ERROR Module coreDstMAC3E8DE3DACB3E already exists
2024-02-08 08:06:09,215 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection coreRoutes:0->0:coreDstMAC3E8DE3DACB3E failed
2024-02-08 08:06:09,218 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:11,226 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection coreRoutes:0->0:coreDstMAC3E8DE3DACB3E failed
2024-02-08 08:06:11,227 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:13,235 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection coreRoutes:0->0:coreDstMAC3E8DE3DACB3E failed
2024-02-08 08:06:13,236 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:15,245 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection coreRoutes:0->0:coreDstMAC3E8DE3DACB3E failed
2024-02-08 08:06:15,246 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:17,254 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection coreRoutes:0->0:coreDstMAC3E8DE3DACB3E failed
2024-02-08 08:06:17,255 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:19,261 ERROR Error linking module coreDstMAC3E8DE3DACB3E to module coreRoutes
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 490, in _create_module_links
self._bess_controller.link_modules(
File "/opt/bess/bessctl/conf/route_control.py", line 269, in link_modules
raise Exception(
Exception: BESS module connection (coreRoutes:0->0:coreDstMAC3E8DE3DACB3E) failure.
2024-02-08 08:06:19,267 INFO Mac address found for 192.168.252.1, Mac: 26:9f:6a:c1:e4:13
2024-02-08 08:06:19,270 INFO Route entry 192.168.251.0/24 added to accessRoutes
2024-02-08 08:06:19,275 INFO Neighbor entry does not exist, creating modules.
2024-02-08 08:06:19,277 ERROR Module accessDstMAC269F6AC1E413 already exists
2024-02-08 08:06:19,284 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection accessRoutes:0->0:accessDstMAC269F6AC1E413 failed
2024-02-08 08:06:19,285 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:21,294 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection accessRoutes:0->0:accessDstMAC269F6AC1E413 failed
2024-02-08 08:06:21,295 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:23,304 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection accessRoutes:0->0:accessDstMAC269F6AC1E413 failed
2024-02-08 08:06:23,305 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:25,313 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection accessRoutes:0->0:accessDstMAC269F6AC1E413 failed
2024-02-08 08:06:25,314 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:27,323 ERROR Got BESS error
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 239, in link_modules
self._bess.connect_modules(module, next_module, ogate, igate)
File "/opt/bess/pybess/bess.py", line 489, in connect_modules
return self._request('ConnectModules', request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/bess/pybess/bess.py", line 280, in _request
raise self.Error(code, errmsg, query=name, query_arg=req_dict)
pybess.bess.BESS.Error: errno=16 (EBUSY: Device or resource busy), Connection accessRoutes:0->0:accessDstMAC269F6AC1E413 failed
2024-02-08 08:06:27,324 ERROR Got code EBUSY. Retrying in 2 secs...
2024-02-08 08:06:29,330 ERROR Error linking module accessDstMAC269F6AC1E413 to module accessRoutes
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 490, in _create_module_links
self._bess_controller.link_modules(
File "/opt/bess/bessctl/conf/route_control.py", line 269, in link_modules
raise Exception(
Exception: BESS module connection (accessRoutes:0->0:accessDstMAC269F6AC1E413) failure.
2024-02-08 08:06:29,332 INFO Registering netlink event listener handler...
Traceback (most recent call last):
File "/opt/bess/bessctl/conf/route_control.py", line 810, in
route_controller.register_handlers()
File "/opt/bess/bessctl/conf/route_control.py", line 352, in register_handlers
self._event_callback = self._ndb.register_handler(ifinfmsg,
^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NDB' object has no attribute 'register_handler'

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like register_handler is now part of the class TaskManager. Here.
And I see it being called in some places of the ndb code as self.ndb.task_manager.register_handler(<event>, <handler>)
Like here.
And it seems to me as if register_handler has been wrapped into TmpHandler
And it is used here in ndb objects to register handlers too.
I didn't go into details to understand how it works so I'm not sure if we can leverage TmpHandler or ndb objects, or if we should use the function directly and for some reason I'm unable to access the docs on https://docs.pyroute2.org.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a look at it and it seems really poorly documented. TaskManager and TmpHandler are not mentioned at all in the documentation. TaskManager is a public attribute of NDB, so I think it would be reasonable to use it, but we would have to test it out.

Another approach we could take is to create a polling thread in routectl (or reuse the pinging thread) to trigger the BESS configuration when the MAC address is present.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using the task_manager, then the register_handler works as expected and the pipeline for the N3 (access) interface is completed. However, the pipeline for the N6 (core) interface is still incomplete.

$ kubectl -n omec logs upf-0 -c routectl
2024-02-22 05:02:28,909 INFO Connected to BESS daemon
2024-02-22 05:02:28,921 INFO Mac address not found for 192.168.250.1
2024-02-22 05:02:28,921 INFO mac address of the next hop 192.168.250.1 is not stored in ARP table. Probing...
2024-02-22 05:02:28,921 INFO Adding entry RouteEntry(next_hop_ip='192.168.250.1', interface='core', dest_prefix='0.0.0.0', prefix_len=0) in arp table by pinging
2024-02-22 05:02:28,921 INFO Sending ping to 192.168.250.1
.
Sent 1 packets.
2024-02-22 05:02:29,102 INFO Mac address found for 192.168.252.1, Mac: ca:14:78:27:df:ba
2024-02-22 05:02:29,106 INFO Route entry 192.168.251.0/24 added to accessRoutes
2024-02-22 05:02:29,111 INFO Neighbor entry does not exist, creating modules.
2024-02-22 05:02:29,114 INFO Add Update module accessDstMACCA147827DFBA successfully
2024-02-22 05:02:29,121 INFO Module accessRoutes:0->0/accessDstMACCA147827DFBA linked
2024-02-22 05:02:29,128 INFO Module accessDstMACCA147827DFBA:0->0/accessMerge linked
2024-02-22 05:02:29,133 INFO Registering netlink event listener handler...
2024-02-22 05:02:29,134 INFO Missing ARP entries: ['192.168.250.1']
2024-02-22 05:02:29,134 INFO Sending ping to 192.168.250.1
2024-02-22 05:02:29,136 INFO Ping missing entries thread started
2024-02-22 05:02:29,136 INFO Registering signals handlers.
2024-02-22 05:02:29,136 INFO Sleep until a signal is received
2024-02-22 05:02:29,141 INFO {'family': 0, '__align': (), 'ifi_type': 1, 'index': 5, 'flags': 69699, 'change': 256, 'attrs': [('IFLA_IFNAME', 'core'), ('IFLA_TXQLEN', 0), ('IFLA_OPERSTATE', 'UP'), ('IFLA_LINKMODE', 0), ('IFLA_MTU', 1500), ('IFLA_MIN_MTU', 68), ('IFLA_MAX_MTU', 0), ('IFLA_GROUP', 0), ('IFLA_PROMISCUITY', 1), ('IFLA_NUM_TX_QUEUES', 1), ('IFLA_GSO_MAX_SEGS', 65535), ('IFLA_GSO_MAX_SIZE', 65536), ('IFLA_NUM_RX_QUEUES', 1), ('IFLA_CARRIER', 1), ('IFLA_QDISC', 'noqueue'), ('IFLA_CARRIER_CHANGES', 0), ('IFLA_CARRIER_UP_COUNT', 0), ('IFLA_CARRIER_DOWN_COUNT', 0), ('IFLA_PROTO_DOWN', 0), ('IFLA_MAP', {'mem_start': 0, 'mem_end': 0, 'base_addr': 0, 'irq': 0, 'dma': 0, 'port': 0}), ('IFLA_ADDRESS', '5a:a5:0e:4c:e1:0c'), ('IFLA_BROADCAST', 'ff:ff:ff:ff:ff:ff'), ('IFLA_STATS64', {'rx_packets': 7, 'tx_packets': 13, 'rx_bytes': 336, 'tx_bytes': 962, 'rx_errors': 0, 'tx_errors': 0, 'rx_dropped': 0, 'tx_dropped': 0, 'multicast': 3, 'collisions': 0, 'rx_length_errors': 0, 'rx_over_errors': 0, 'rx_crc_errors': 0, 'rx_frame_errors': 0, 'rx_fifo_errors': 0, 'rx_missed_errors': 0, 'tx_aborted_errors': 0, 'tx_carrier_errors': 0, 'tx_fifo_errors': 0, 'tx_heartbeat_errors': 0, 'tx_window_errors': 0, 'rx_compressed': 0, 'tx_compressed': 0}), ('IFLA_STATS', {'rx_packets': 7, 'tx_packets': 13, 'rx_bytes': 336, 'tx_bytes': 962, 'rx_errors': 0, 'tx_errors': 0, 'rx_dropped': 0, 'tx_dropped': 0, 'multicast': 3, 'collisions': 0, 'rx_length_errors': 0, 'rx_over_errors': 0, 'rx_crc_errors': 0, 'rx_frame_errors': 0, 'rx_fifo_errors': 0, 'rx_missed_errors': 0, 'tx_aborted_errors': 0, 'tx_carrier_errors': 0, 'tx_fifo_errors': 0, 'tx_heartbeat_errors': 0, 'tx_window_errors': 0, 'rx_compressed': 0, 'tx_compressed': 0}), ('IFLA_XDP', {'attrs': [('IFLA_XDP_ATTACHED', None)]}), ('IFLA_LINKINFO', {'attrs': [('IFLA_INFO_KIND', 'macvlan'), ('IFLA_INFO_DATA', {'attrs': [('IFLA_MACVLAN_MODE', 'bridge'), ('IFLA_MACVLAN_FLAGS', 'none'), ('IFLA_MACVLAN_MACADDR_COUNT', 0), ('UNKNOWN', {'header': {'length': 8, 'type': 7}}), ('UNKNOWN', {'header': {'length': 8, 'type': 8}})], 'header': {}, 'index': 5})]}), ('IFLA_LINK_NETNSID', 0), ('IFLA_LINK', 43), ('IFLA_AF_SPEC', {'attrs': [('AF_INET', {'dummy': 65668, 'forwarding': 0, 'mc_forwarding': 0, 'proxy_arp': 0, 'accept_redirects': 1, 'secure_redirects': 1, 'send_redirects': 1, 'shared_media': 1, 'rp_filter': 2, 'accept_source_route': 0, 'bootp_relay': 0, 'log_martians': 0, 'tag': 0, 'arpfilter': 0, 'medium_id': 0, 'noxfrm': 0, 'nopolicy': 0, 'force_igmp_version': 0, 'arp_announce': 0, 'arp_ignore': 0, 'promote_secondaries': 1, 'arp_accept': 0, 'arp_notify': 0, 'accept_local': 0, 'src_vmark': 0, 'proxy_arp_pvlan': 0, 'route_localnet': 0, 'igmpv2_unsolicited_report_interval': 10000, 'igmpv3_unsolicited_report_interval': 1000}), ('AF_INET6', {'attrs': [('IFLA_INET6_FLAGS', 2147483664), ('IFLA_INET6_CACHEINFO', {'max_reasm_len': 65535, 'tstamp': 2631746, 'reachable_time': 34204, 'retrans_time': 1000}), ('IFLA_INET6_CONF', {'forwarding': 0, 'hop_limit': 64, 'mtu': 1500, 'accept_ra': 1, 'accept_redirects': 1, 'autoconf': 1, 'dad_transmits': 1, 'router_solicitations': 4294967295, 'router_solicitation_interval': 4000, 'router_solicitation_delay': 1000, 'use_tempaddr': 0, 'temp_valid_lft': 604800, 'temp_preferred_lft': 86400, 'regen_max_retry': 3, 'max_desync_factor': 600, 'max_addresses': 16, 'force_mld_version': 0, 'accept_ra_defrtr': 1, 'accept_ra_pinfo': 1, 'accept_ra_rtr_pref': 1, 'router_probe_interval': 60000, 'accept_ra_rt_info_max_plen': 0, 'proxy_ndp': 0, 'optimistic_dad': 0, 'accept_source_route': 0, 'mc_forwarding': 0, 'disable_ipv6': 0, 'accept_dad': 1, 'force_tllao': 0, 'ndisc_notify': 0}), ('IFLA_INET6_STATS', {'num': 37, 'inpkts': 0, 'inoctets': 0, 'indelivers': 0, 'outforwdatagrams': 0, 'outpkts': 10, 'outoctets': 696, 'inhdrerrors': 0, 'intoobigerrors': 0, 'innoroutes': 0, 'inaddrerrors': 0, 'inunknownprotos': 0, 'intruncatedpkts': 0, 'indiscards': 0, 'outdiscards': 0, 'outnoroutes': 0, 'reasmtimeout': 0, 'reasmreqds': 0, 'reasmoks': 0, 'reasmfails': 0, 'fragoks': 0, 'fragfails': 0, 'fragcreates': 0, 'inmcastpkts': 0, 'outmcastpkts': 10, 'inbcastpkts': 0, 'outbcastpkts': 0, 'inmcastoctets': 0, 'outmcastoctets': 696, 'inbcastoctets': 0, 'outbcastoctets': 0, 'csumerrors': 0, 'noectpkts': 0, 'ect1pkts': 0, 'ect0pkts': 0, 'cepkts': 0}), ('IFLA_INET6_ICMP6STATS', {'num': 6, 'inmsgs': 0, 'inerrors': 0, 'outmsgs': 10, 'outerrors': 0, 'csumerrors': 0}), ('IFLA_INET6_TOKEN', '::'), ('IFLA_INET6_ADDR_GEN_MODE', 0)]})]})], 'header': {'length': 1428, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}, 'state': 'up', 'event': 'RTM_NEWLINK', 'alt_ifname_list': []} netlink event received.
2024-02-22 05:02:29,143 ERROR Error parsing route entry message
Traceback (most recent call last):
  File "/opt/bess/bessctl/conf/route_control.py", line 659, in _parse_route_entry_msg
    attr_dict = dict(route_entry["attrs"])
                     ~~~~~~~~~~~^^^^^^^^^
TypeError: string indices must be integers, not 'str'
.
Sent 1 packets.
2024-02-22 05:02:29,161 INFO {'family': 0, '__align': (), 'ifi_type': 1, 'index': 5, 'flags': 69699, 'change': 256, 'attrs': [('IFLA_IFNAME', 'core'), ('IFLA_TXQLEN', 0), ('IFLA_OPERSTATE', 'UP'), ('IFLA_LINKMODE', 0), ('IFLA_MTU', 1500), ('IFLA_MIN_MTU', 68), ('IFLA_MAX_MTU', 0), ('IFLA_GROUP', 0), ('IFLA_PROMISCUITY', 0), ('IFLA_NUM_TX_QUEUES', 1), ('IFLA_GSO_MAX_SEGS', 65535), ('IFLA_GSO_MAX_SIZE', 65536), ('IFLA_NUM_RX_QUEUES', 1), ('IFLA_CARRIER', 1), ('IFLA_QDISC', 'noqueue'), ('IFLA_CARRIER_CHANGES', 0), ('IFLA_CARRIER_UP_COUNT', 0), ('IFLA_CARRIER_DOWN_COUNT', 0), ('IFLA_PROTO_DOWN', 0), ('IFLA_MAP', {'mem_start': 0, 'mem_end': 0, 'base_addr': 0, 'irq': 0, 'dma': 0, 'port': 0}), ('IFLA_ADDRESS', '5a:a5:0e:4c:e1:0c'), ('IFLA_BROADCAST', 'ff:ff:ff:ff:ff:ff'), ('IFLA_STATS64', {'rx_packets': 8, 'tx_packets': 14, 'rx_bytes': 378, 'tx_bytes': 1004, 'rx_errors': 0, 'tx_errors': 0, 'rx_dropped': 0, 'tx_dropped': 0, 'multicast': 3, 'collisions': 0, 'rx_length_errors': 0, 'rx_over_errors': 0, 'rx_crc_errors': 0, 'rx_frame_errors': 0, 'rx_fifo_errors': 0, 'rx_missed_errors': 0, 'tx_aborted_errors': 0, 'tx_carrier_errors': 0, 'tx_fifo_errors': 0, 'tx_heartbeat_errors': 0, 'tx_window_errors': 0, 'rx_compressed': 0, 'tx_compressed': 0}), ('IFLA_STATS', {'rx_packets': 8, 'tx_packets': 14, 'rx_bytes': 378, 'tx_bytes': 1004, 'rx_errors': 0, 'tx_errors': 0, 'rx_dropped': 0, 'tx_dropped': 0, 'multicast': 3, 'collisions': 0, 'rx_length_errors': 0, 'rx_over_errors': 0, 'rx_crc_errors': 0, 'rx_frame_errors': 0, 'rx_fifo_errors': 0, 'rx_missed_errors': 0, 'tx_aborted_errors': 0, 'tx_carrier_errors': 0, 'tx_fifo_errors': 0, 'tx_heartbeat_errors': 0, 'tx_window_errors': 0, 'rx_compressed': 0, 'tx_compressed': 0}), ('IFLA_XDP', {'attrs': [('IFLA_XDP_ATTACHED', None)]}), ('IFLA_LINKINFO', {'attrs': [('IFLA_INFO_KIND', 'macvlan'), ('IFLA_INFO_DATA', {'attrs': [('IFLA_MACVLAN_MODE', 'bridge'), ('IFLA_MACVLAN_FLAGS', 'none'), ('IFLA_MACVLAN_MACADDR_COUNT', 0), ('UNKNOWN', {'header': {'length': 8, 'type': 7}}), ('UNKNOWN', {'header': {'length': 8, 'type': 8}})], 'header': {}, 'index': 5})]}), ('IFLA_LINK_NETNSID', 0), ('IFLA_LINK', 43), ('IFLA_AF_SPEC', {'attrs': [('AF_INET', {'dummy': 65668, 'forwarding': 0, 'mc_forwarding': 0, 'proxy_arp': 0, 'accept_redirects': 1, 'secure_redirects': 1, 'send_redirects': 1, 'shared_media': 1, 'rp_filter': 2, 'accept_source_route': 0, 'bootp_relay': 0, 'log_martians': 0, 'tag': 0, 'arpfilter': 0, 'medium_id': 0, 'noxfrm': 0, 'nopolicy': 0, 'force_igmp_version': 0, 'arp_announce': 0, 'arp_ignore': 0, 'promote_secondaries': 1, 'arp_accept': 0, 'arp_notify': 0, 'accept_local': 0, 'src_vmark': 0, 'proxy_arp_pvlan': 0, 'route_localnet': 0, 'igmpv2_unsolicited_report_interval': 10000, 'igmpv3_unsolicited_report_interval': 1000}), ('AF_INET6', {'attrs': [('IFLA_INET6_FLAGS', 2147483664), ('IFLA_INET6_CACHEINFO', {'max_reasm_len': 65535, 'tstamp': 2631746, 'reachable_time': 34204, 'retrans_time': 1000}), ('IFLA_INET6_CONF', {'forwarding': 0, 'hop_limit': 64, 'mtu': 1500, 'accept_ra': 1, 'accept_redirects': 1, 'autoconf': 1, 'dad_transmits': 1, 'router_solicitations': 4294967295, 'router_solicitation_interval': 4000, 'router_solicitation_delay': 1000, 'use_tempaddr': 0, 'temp_valid_lft': 604800, 'temp_preferred_lft': 86400, 'regen_max_retry': 3, 'max_desync_factor': 600, 'max_addresses': 16, 'force_mld_version': 0, 'accept_ra_defrtr': 1, 'accept_ra_pinfo': 1, 'accept_ra_rtr_pref': 1, 'router_probe_interval': 60000, 'accept_ra_rt_info_max_plen': 0, 'proxy_ndp': 0, 'optimistic_dad': 0, 'accept_source_route': 0, 'mc_forwarding': 0, 'disable_ipv6': 0, 'accept_dad': 1, 'force_tllao': 0, 'ndisc_notify': 0}), ('IFLA_INET6_STATS', {'num': 37, 'inpkts': 0, 'inoctets': 0, 'indelivers': 0, 'outforwdatagrams': 0, 'outpkts': 10, 'outoctets': 696, 'inhdrerrors': 0, 'intoobigerrors': 0, 'innoroutes': 0, 'inaddrerrors': 0, 'inunknownprotos': 0, 'intruncatedpkts': 0, 'indiscards': 0, 'outdiscards': 0, 'outnoroutes': 0, 'reasmtimeout': 0, 'reasmreqds': 0, 'reasmoks': 0, 'reasmfails': 0, 'fragoks': 0, 'fragfails': 0, 'fragcreates': 0, 'inmcastpkts': 0, 'outmcastpkts': 10, 'inbcastpkts': 0, 'outbcastpkts': 0, 'inmcastoctets': 0, 'outmcastoctets': 696, 'inbcastoctets': 0, 'outbcastoctets': 0, 'csumerrors': 0, 'noectpkts': 0, 'ect1pkts': 0, 'ect0pkts': 0, 'cepkts': 0}), ('IFLA_INET6_ICMP6STATS', {'num': 6, 'inmsgs': 0, 'inerrors': 0, 'outmsgs': 10, 'outerrors': 0, 'csumerrors': 0}), ('IFLA_INET6_TOKEN', '::'), ('IFLA_INET6_ADDR_GEN_MODE', 0)]})]})], 'header': {'length': 1428, 'type': 16, 'flags': 0, 'sequence_number': 0, 'pid': 0, 'error': None, 'target': 'localhost', 'stats': Stats(qsize=0, delta=0, delay=0)}, 'state': 'up', 'event': 'RTM_NEWLINK', 'alt_ifname_list': []} netlink event received.
2024-02-22 05:02:29,163 ERROR Error parsing route entry message
Traceback (most recent call last):
  File "/opt/bess/bessctl/conf/route_control.py", line 659, in _parse_route_entry_msg
    attr_dict = dict(route_entry["attrs"])
                     ~~~~~~~~~~~^^^^^^^^^
TypeError: string indices must be integers, not 'str'

image
image

route_controller.start_pinging_missing_entries()
register_signal_handlers(route_controller=route_controller)
logger.info("Sleep until a signal is received")
Expand Down
104 changes: 65 additions & 39 deletions conf/test_route_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import unittest
from unittest.mock import MagicMock, Mock, patch

from pyroute2 import IPDB # type: ignore[import]

sys.modules["pybess.bess"] = MagicMock()

from conf.route_control import (NeighborEntry, RouteController, RouteEntry,
Expand Down Expand Up @@ -50,7 +48,7 @@ def test_given_valid_ip_when_validate_ipv4_then_returns_true(self):
def test_given_invalid_ip_when_validate_ipv4_then_returns_false(self):
self.assertFalse(validate_ipv4("192.168.300.1"))

def test_given_invalid_ip_when_validate_ipv4_then_returns_false(self):
def test_given_invalid_ip_when_validate_ipv6_then_returns_false(self):
self.assertFalse(validate_ipv4("::1"))
self.assertFalse(validate_ipv4(""))

Expand All @@ -67,27 +65,35 @@ def test_given_valid_mac_when_mac_to_hex_then_return_hex_string_representation(
self.assertEqual(mac_to_hex("00:1a:2b:3c:4d:5e"), "001A2B3C4D5E")

def test_given_known_destination_when_fetch_mac_then_returns_mac(self):
ipdb = IPDB()
ipdb.nl.get_neighbours = lambda dst, **kwargs: [
{"attrs": [("NDA_DST", dst), ("NDA_LLADDR", "00:1a:2b:3c:4d:5e")]}
]
self.assertEqual(fetch_mac(ipdb, "192.168.1.1"), "00:1a:2b:3c:4d:5e")
ndb = Mock()
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": "00:1a:2b:3c:4d:5e"
}
ndb.neighbours.dump.return_value = [kwargs]
self.assertEqual(fetch_mac(ndb, "192.168.1.1"), "00:1a:2b:3c:4d:5e")

def test_given_unkonw_destination_when_fetch_mac_then_returns_none(self):
ipdb = IPDB()
ipdb.nl.get_neighbours = lambda dst, **kwargs: []
self.assertIsNone(fetch_mac(ipdb, "192.168.1.1"))
ndb = Mock()
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": None
}
ndb.neighbours.dump.return_value = [kwargs]
self.assertIsNone(fetch_mac(ndb, "192.168.1.1"))


class TestRouteController(unittest.TestCase):
def setUp(self):
self.mock_bess_controller = Mock(BessControllerMock)
self.ipdb = Mock()
self.ndb = Mock()
self.ipr = Mock()
interfaces = ["access", "core"]
self.route_controller = RouteController(
self.mock_bess_controller,
self.ipdb,
self.ndb,
interfaces=interfaces,
ipr=self.ipr,
)
Expand All @@ -105,9 +111,12 @@ def add_route_entry(
mock_fetch_mac,
) -> None:
"""Adds a new route entry using the route controller."""
self.ipdb.nl.get_neighbours = lambda dst, **kwargs: [
{"attrs": [("NDA_DST", dst), ("NDA_LLADDR", "00:1a:2b:3c:4d:5e")]}
]
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": "00:1a:2b:3c:4d:5e"
}
self.ndb.neighbours.dump.return_value = [kwargs]
mock_get_update_module_name.return_value = "merge_module"
mock_get_route_module_name.return_value = "route_module"
mock_get_merge_module_name.return_value = "update_module"
Expand All @@ -116,7 +125,7 @@ def add_route_entry(
return route_entry

def test_given_valid_route_message_when_parse_message_then_parses_message(self):
self.ipdb.interfaces = {2: Mock(ifname="core")}
self.ndb.interfaces = {2: {"ifname": "core"}}
example_route_entry = {
"family": 2,
"dst_len": 24,
Expand All @@ -141,13 +150,13 @@ def test_given_valid_route_message_when_parse_message_then_parses_message(self):
self.assertIsInstance(result, RouteEntry)
self.assertEqual(result.dest_prefix, "192.168.1.0")
self.assertEqual(result.next_hop_ip, "172.31.48.1")
self.assertEqual(result.interface, self.ipdb.interfaces[2].ifname)
self.assertEqual(result.interface, self.ndb.interfaces[2].get("ifname"))
self.assertEqual(result.prefix_len, 24)

def test_given_valid_route_message_and_dst_len_is_zero_when_parse_message_then_parses_message_as_default_route(
self,
):
self.ipdb.interfaces = {2: Mock(ifname="core")}
self.ndb.interfaces = {2: {"ifname": "core"}}
example_route_entry = {
"family": 2,
"dst_len": 0,
Expand All @@ -171,11 +180,11 @@ def test_given_valid_route_message_and_dst_len_is_zero_when_parse_message_then_p
self.assertIsInstance(result, RouteEntry)
self.assertEqual(result.dest_prefix, "0.0.0.0")
self.assertEqual(result.next_hop_ip, "172.31.48.1")
self.assertEqual(result.interface, self.ipdb.interfaces[2].ifname)
self.assertEqual(result.interface, self.ndb.interfaces[2].get("ifname"))
self.assertEqual(result.prefix_len, 0)

def test_given_invalid_route_message_when_parse_message_then_returns_none(self):
self.ipdb.interfaces = {2: Mock(ifname="not the needed interface")}
self.ndb.interfaces = {2: {"ifname": "not the needed interface"}}
example_route_entry = {
"family": 2,
"flags": 0,
Expand All @@ -202,7 +211,12 @@ def test_given_new_route_when_add_new_route_entry_and_mac_not_known_then_destina
self,
mock_send_ping,
):
self.ipdb.nl.get_neighbours = lambda dst, **kwargs: []
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": None
}
self.ndb.neighbours.dump.return_value = [kwargs]
route_entry = RouteEntry(
next_hop_ip="1.2.3.4",
interface="random_interface",
Expand All @@ -212,12 +226,16 @@ def test_given_new_route_when_add_new_route_entry_and_mac_not_known_then_destina
self.route_controller.add_new_route_entry(route_entry)
mock_send_ping.assert_called_once()

@patch("conf.route_control.send_ping")
def test_given_valid_new_route_when_add_new_route_entry_and_mac_known_then_route_is_added_in_bess(
self,
self, _
):
self.ipdb.nl.get_neighbours = lambda dst, **kwargs: [
{"attrs": [("NDA_DST", dst), ("NDA_LLADDR", "00:1a:2b:3c:4d:5e")]}
]
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": "00:1a:2b:3c:4d:5e"
}
self.ndb.neighbours.dump.return_value = [kwargs]
mock_routes = [{"event": "RTM_NEWROUTE"}, {"event": "OTHER_ACTION"}]
self.ipr.get_routes.return_value = mock_routes
route_entry = RouteEntry(
Expand All @@ -227,14 +245,19 @@ def test_given_valid_new_route_when_add_new_route_entry_and_mac_known_then_route
prefix_len=24,
)
self.route_controller.add_new_route_entry(route_entry)
self.mock_bess_controller.add_route_to_module()
self.mock_bess_controller.add_route_to_module.assert_called_once()

@patch("conf.route_control.send_ping")
def test_given_valid_new_route_when_add_new_route_entry_and_mac_known_and_neighbor_not_known_then_update_module_is_created_and_modules_are_linked(
self,
self, _
):
self.ipdb.nl.get_neighbours = lambda dst, **kwargs: [
{"attrs": [("NDA_DST", dst), ("NDA_LLADDR", "00:1a:2b:3c:4d:5e")]}
]
kwargs = {
"ifindex": 1,
"dst": "1.2.3.4",
"lladdr": "00:1a:2b:3c:4d:5e"
}
self.ndb.neighbours.dump.return_value = [kwargs]
mock_routes = [{"event": "RTM_NEWROUTE"}, {"event": "OTHER_ACTION"}]
self.ipr.get_routes.return_value = mock_routes
route_entry = RouteEntry(
Expand Down Expand Up @@ -265,7 +288,7 @@ def test_given_new_route_when_bootstrap_routes_then_add_new_entry_is_called(
{"event": "OTHER_ACTION"},
]
self.ipr.get_routes.return_value = mock_routes
self.ipdb.interfaces = {2: Mock(ifname="core")}
self.ndb.interfaces = {2: {"ifname": "core"}}
valid_route_entry = RouteEntry(
next_hop_ip="1.2.3.4",
interface="core",
Expand Down Expand Up @@ -322,7 +345,7 @@ def test_given_new_route_and_invalid_message_when_bootstrap_routes_then_add_new_
def test_given_netlink_message_when_rtm_newroute_event_then_add_new_route_entry_is_called(
self, mock_add_new_route_entry
):
self.ipdb.interfaces = {2: Mock(ifname="core")}
self.ndb.interfaces = {2: {"ifname": "core"}}
example_route_entry = {
"family": 2,
"dst_len": 24,
Expand All @@ -344,7 +367,7 @@ def test_given_netlink_message_when_rtm_newroute_event_then_add_new_route_entry_
"event": "RTM_NEWROUTE",
}
self.route_controller._netlink_event_listener(
self.ipdb, example_route_entry, "RTM_NEWROUTE"
self.ndb, example_route_entry, "RTM_NEWROUTE"
)
mock_add_new_route_entry.assert_called()

Expand Down Expand Up @@ -398,7 +421,7 @@ def test_given_existing_neighbor_and_route_count_is_one_when_delete_route_entry_
def test_given_netlink_message_when_rtm_delroute_event_then_delete_route_entry_is_called(
self, mock_delete_route_entry
):
self.ipdb.interfaces = {2: Mock(ifname="core")}
self.ndb.interfaces = {2: {"ifname": "core"}}
example_route_entry = {
"family": 2,
"dst_len": 24,
Expand All @@ -420,7 +443,7 @@ def test_given_netlink_message_when_rtm_delroute_event_then_delete_route_entry_i
"event": "RTM_DELROUTE",
}
self.route_controller._netlink_event_listener(
self.ipdb, example_route_entry, "RTM_DELROUTE"
self.ndb, example_route_entry, "RTM_DELROUTE"
)
mock_delete_route_entry.assert_called()

Expand All @@ -429,9 +452,12 @@ def test_given_new_neighbor_in_unresolved_when_add_unresolved_new_neighbor_then_
self,
_,
):
self.ipdb.nl.get_neighbours = lambda dst, **kwargs: [
{"attrs": [("NDA_DST", dst), ("NDA_LLADDR", "00:1a:2b:3c:4d:5e")]}
]
kwargs = {
"ifindex": 1,
"dst": "192.168.1.1",
"lladdr": "00:1a:2b:3c:4d:5e"
}
self.ndb.neighbours.dump.return_value = [kwargs]
mock_netlink_msg = {
"attrs": {
"NDA_DST": "1.2.3.4",
Expand All @@ -455,6 +481,6 @@ def test_given_netlink_message_when_rtm_newneigh_event_then_add_unresolved_new_n
self, mock_add_unresolved_new_neighbor
):
self.route_controller._netlink_event_listener(
self.ipdb, "new neighbour message", "RTM_NEWNEIGH"
self.ndb, "new neighbour message", "RTM_NEWNEIGH"
)
mock_add_unresolved_new_neighbor.assert_called()
Loading
Loading