daemon: refactoring to tracking wireless link information

This commit is contained in:
Blake Harnden 2022-04-05 12:05:37 -07:00
parent 440c06c040
commit ea751727b4

View file

@ -33,11 +33,17 @@ def calc_distance(
return math.hypot(math.hypot(a, b), c) return math.hypot(math.hypot(a, b), c)
def get_key(node1_id: int, node2_id: int) -> Tuple[int, int]:
return (node1_id, node2_id) if node1_id < node2_id else (node2_id, node1_id)
@dataclass @dataclass
class WirelessLink: class WirelessLink:
bridge1: str bridge1: str
bridge2: str bridge2: str
iface: CoreInterface iface: CoreInterface
linked: bool
label: str = None
class WirelessNode(CoreNetworkBase): class WirelessNode(CoreNetworkBase):
@ -53,7 +59,6 @@ class WirelessNode(CoreNetworkBase):
super().__init__(session, _id, name, server) super().__init__(session, _id, name, server)
self.bridges: Dict[int, Tuple[CoreInterface, str]] = {} self.bridges: Dict[int, Tuple[CoreInterface, str]] = {}
self.links: Dict[Tuple[int, int], WirelessLink] = {} self.links: Dict[Tuple[int, int], WirelessLink] = {}
self.labels: Dict[Tuple[int, int], str] = {}
def startup(self) -> None: def startup(self) -> None:
if self.up: if self.up:
@ -117,7 +122,7 @@ class WirelessNode(CoreNetworkBase):
name2 = f"we{self.id}.{node2.id}.{node1.id}.{session_id}" name2 = f"we{self.id}.{node2.id}.{node1.id}.{session_id}"
link_iface = CoreInterface(0, name1, name2, self.session.use_ovs()) link_iface = CoreInterface(0, name1, name2, self.session.use_ovs())
link_iface.startup() link_iface.startup()
link = WirelessLink(bridge1, bridge2, link_iface) link = WirelessLink(bridge1, bridge2, link_iface, True)
self.links[key] = link self.links[key] = link
# assign ifaces to respective bridges # assign ifaces to respective bridges
self.net_client.set_iface_master(bridge1, link_iface.name) self.net_client.set_iface_master(bridge1, link_iface.name)
@ -148,27 +153,27 @@ class WirelessNode(CoreNetworkBase):
) )
def link_control(self, node1_id: int, node2_id: int, linked: bool) -> None: def link_control(self, node1_id: int, node2_id: int, linked: bool) -> None:
key = (node1_id, node2_id) if node1_id < node2_id else (node2_id, node1_id) key = get_key(node1_id, node2_id)
link = self.links.get(key) link = self.links.get(key)
if not link: if not link:
raise CoreError(f"invalid node links node1({node1_id}) node2({node2_id})") raise CoreError(f"invalid node links node1({node1_id}) node2({node2_id})")
bridge1, bridge2 = link.bridge1, link.bridge2 bridge1, bridge2 = link.bridge1, link.bridge2
iface = link.iface iface = link.iface
if linked: if not link.linked and linked:
link.linked = True
self.net_client.set_iface_master(bridge1, iface.name) self.net_client.set_iface_master(bridge1, iface.name)
self.net_client.set_iface_master(bridge2, iface.localname) self.net_client.set_iface_master(bridge2, iface.localname)
message_type = MessageFlags.ADD self.send_link(key[0], key[1], MessageFlags.ADD, link.label)
else: elif link.linked and not linked:
link.linked = False
self.net_client.delete_iface(bridge1, iface.name) self.net_client.delete_iface(bridge1, iface.name)
self.net_client.delete_iface(bridge2, iface.localname) self.net_client.delete_iface(bridge2, iface.localname)
message_type = MessageFlags.DELETE self.send_link(key[0], key[1], MessageFlags.DELETE, link.label)
label = self.labels.get(key)
self.send_link(key[0], key[1], message_type, label)
def link_config( def link_config(
self, node1_id: int, node2_id: int, options1: LinkOptions, options2: LinkOptions self, node1_id: int, node2_id: int, options1: LinkOptions, options2: LinkOptions
) -> None: ) -> None:
key = (node1_id, node2_id) if node1_id < node2_id else (node2_id, node1_id) key = get_key(node1_id, node2_id)
link = self.links.get(key) link = self.links.get(key)
if not link: if not link:
raise CoreError(f"invalid node links node1({node1_id}) node2({node2_id})") raise CoreError(f"invalid node links node1({node1_id}) node2({node2_id})")
@ -183,14 +188,13 @@ class WirelessNode(CoreNetworkBase):
iface.set_config() iface.set_config()
iface.name, iface.localname = name, localname iface.name, iface.localname = name, localname
if options1 == options2: if options1 == options2:
label = f"{options1.loss:.2f}%/{options1.delay}us" link.label = f"{options1.loss:.2f}%/{options1.delay}us"
else: else:
label = ( link.label = (
f"({options1.loss:.2f}%/{options1.delay}us) " f"({options1.loss:.2f}%/{options1.delay}us) "
f"({options2.loss:.2f}%/{options2.delay}us)" f"({options2.loss:.2f}%/{options2.delay}us)"
) )
self.labels[key] = label self.send_link(key[0], key[1], MessageFlags.NONE, link.label)
self.send_link(key[0], key[1], MessageFlags.NONE, label)
def send_link( def send_link(
self, self,
@ -224,15 +228,18 @@ class WirelessNode(CoreNetworkBase):
for oiface, bridge_name in self.bridges.values(): for oiface, bridge_name in self.bridges.values():
if iface == oiface: if iface == oiface:
continue continue
point1 = iface.node.position.get() self.calc_link(iface, oiface)
point2 = oiface.node.position.get()
distance = calc_distance(point1, point2) - 250 def calc_link(self, iface1: CoreInterface, iface2: CoreInterface) -> None:
distance = max(distance, 0.0) point1 = iface1.node.position.get()
loss = min((distance / 500) * 100.0, 100.0) point2 = iface2.node.position.get()
node1_id = iface.node.id distance = calc_distance(point1, point2) - 250
node2_id = oiface.node.id distance = max(distance, 0.0)
options = LinkOptions(loss=loss, delay=0) loss = min((distance / 500) * 100.0, 100.0)
self.link_config(node1_id, node2_id, options, options) node1_id = iface1.node.id
node2_id = iface2.node.id
options = LinkOptions(loss=loss, delay=0)
self.link_config(node1_id, node2_id, options, options)
def adopt_iface(self, iface: CoreInterface, name: str) -> None: def adopt_iface(self, iface: CoreInterface, name: str) -> None:
raise CoreError(f"{type(self)} does not support adopt interface") raise CoreError(f"{type(self)} does not support adopt interface")