daemon: small cleanup to nftables management

This commit is contained in:
Blake Harnden 2021-05-10 20:34:10 -07:00
parent 11d8bb0674
commit 5286938e44

View file

@ -7,7 +7,7 @@ import math
import threading import threading
import time import time
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Callable, Dict, List, Optional, Type from typing import TYPE_CHECKING, Dict, List, Optional, Set, Type
import netaddr import netaddr
@ -36,7 +36,6 @@ if TYPE_CHECKING:
WirelessModelType = Type[WirelessModel] WirelessModelType = Type[WirelessModel]
LEARNING_DISABLED: int = 0 LEARNING_DISABLED: int = 0
NFTABLES_LOCK: threading.Lock = threading.Lock()
class NftablesQueue: class NftablesQueue:
@ -63,7 +62,7 @@ class NftablesQueue:
# list of pending nftables commands # list of pending nftables commands
self.cmds: List[str] = [] self.cmds: List[str] = []
# list of WLANs requiring update # list of WLANs requiring update
self.updates: List["CoreNetwork"] = [] self.updates: Set["CoreNetwork"] = set()
# timestamps of last WLAN update; this keeps track of WLANs that are # timestamps of last WLAN update; this keeps track of WLANs that are
# using this queue # using this queue
self.last_update_time: Dict["CoreNetwork", float] = {} self.last_update_time: Dict["CoreNetwork", float] = {}
@ -101,24 +100,11 @@ class NftablesQueue:
""" """
Return the time elapsed since this network was last updated. Return the time elapsed since this network was last updated.
:param net: network node :param net: network node
:return: elpased time :return: elapsed time
""" """
if net in self.last_update_time: now = time.monotonic()
elapsed = time.monotonic() - self.last_update_time[net] last_update = self.last_update_time.setdefault(net, now)
else: return now - last_update
self.last_update_time[net] = time.monotonic()
elapsed = 0.0
return elapsed
def updated(self, net: "CoreNetwork") -> None:
"""
Keep track of when this network was last updated.
:param net: network node
:return: nothing
"""
self.last_update_time[net] = time.monotonic()
self.updates.remove(net)
def run(self) -> None: def run(self) -> None:
""" """
@ -130,14 +116,18 @@ class NftablesQueue:
""" """
while self.running: while self.running:
with self.lock: with self.lock:
discard = set()
for net in self.updates: for net in self.updates:
if not net.up: if not net.up:
self.updated(net) self.last_update_time[net] = time.monotonic()
discard.add(net)
continue continue
if self.last_update(net) > self.rate: if self.last_update(net) > self.rate:
self.build_cmds(net) self.build_cmds(net)
self.commit(net) self.commit(net)
self.updated(net) self.last_update_time[net] = time.monotonic()
discard.add(net)
self.updates -= discard
time.sleep(self.rate) time.sleep(self.rate)
def commit(self, net: "CoreNetwork") -> None: def commit(self, net: "CoreNetwork") -> None:
@ -164,8 +154,18 @@ class NftablesQueue:
:return: nothing :return: nothing
""" """
with self.lock: with self.lock:
if net not in self.updates: self.updates.add(net)
self.updates.append(net)
def delete_table(self, net: "CoreNetwork") -> None:
"""
Delete nftable bridge rule table.
:param net: network to delete table for
:param name: name of bridge table to delete
:return: nothing
"""
with self.lock:
net.host_cmd(f"{NFTABLES} delete table bridge {net.brname}")
def build_cmds(self, net: "CoreNetwork") -> None: def build_cmds(self, net: "CoreNetwork") -> None:
""" """
@ -215,19 +215,6 @@ class NftablesQueue:
nft_queue: NftablesQueue = NftablesQueue() nft_queue: NftablesQueue = NftablesQueue()
def nftables_cmds(call: Callable[..., str], cmds: List[str]) -> None:
"""
Run nftable commands.
:param call: function to call commands
:param cmds: commands to call
:return: nothing
"""
with NFTABLES_LOCK:
for cmd in cmds:
call(cmd)
class CoreNetwork(CoreNetworkBase): class CoreNetwork(CoreNetworkBase):
""" """
Provides linux bridge network functionality for core nodes. Provides linux bridge network functionality for core nodes.
@ -312,8 +299,7 @@ class CoreNetwork(CoreNetworkBase):
try: try:
self.net_client.delete_bridge(self.brname) self.net_client.delete_bridge(self.brname)
if self.has_nftables_chain: if self.has_nftables_chain:
cmds = [f"{NFTABLES} delete table bridge {self.brname}"] nft_queue.delete_table(self)
nftables_cmds(self.host_cmd, cmds)
except CoreCommandError: except CoreCommandError:
logging.exception("error during shutdown") logging.exception("error during shutdown")
# removes veth pairs used for bridge-to-bridge connections # removes veth pairs used for bridge-to-bridge connections