diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/vyos/ifconfig/vpp/__init__.py | 24 | ||||
| -rw-r--r-- | python/vyos/ifconfig/vpp/bond.py | 152 | ||||
| -rw-r--r-- | python/vyos/ifconfig/vpp/interface.py | 56 | ||||
| -rw-r--r-- | python/vyos/vpp/interface/__init__.py | 2 | ||||
| -rw-r--r-- | python/vyos/vpp/interface/bond.py | 122 | ||||
| -rw-r--r-- | python/vyos/vpp/utils.py | 4 |
6 files changed, 234 insertions, 126 deletions
diff --git a/python/vyos/ifconfig/vpp/__init__.py b/python/vyos/ifconfig/vpp/__init__.py new file mode 100644 index 000000000..117acb8d0 --- /dev/null +++ b/python/vyos/ifconfig/vpp/__init__.py @@ -0,0 +1,24 @@ +# +# Copyright (C) VyOS Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from .bond import VPPBondInterface +from .interface import VPPInterface + +__all__ = [ + 'VPPBondInterface', + 'VPPInterface', +] diff --git a/python/vyos/ifconfig/vpp/bond.py b/python/vyos/ifconfig/vpp/bond.py new file mode 100644 index 000000000..75849a620 --- /dev/null +++ b/python/vyos/ifconfig/vpp/bond.py @@ -0,0 +1,152 @@ +# +# Copyright (C) VyOS Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from vyos.ifconfig import Interface +from vyos.ifconfig.vpp.interface import VPPInterface + + +class VPPBondInterface(Interface, VPPInterface): + def __init__(self, ifname, config): + self.ifname = ifname + self.instance = int(ifname.removeprefix('vppbond')) + self.vpp_ifname = f'BondEthernet{self.instance}' + + # Initialize Interface (kernel) and VPP part + super().__init__(ifname) + VPPInterface.__init__(self, self.vpp_ifname) + + self.index = self.vpp.get_sw_if_index(self.vpp_ifname) + self.state = 'up' if 'disable' not in config else 'down' + self.mode = config.get('mode') + self.load_balance = config.get('hash_policy') + self.mac = config.get('mac') + + def _create(self): + pass + + def add_bond(self): + """Create Bond interface + https://github.com/FDio/vpp/blob/stable/2306/src/vnet/bonding/bond.api + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = BondInterface(ifname='vppbond0', config) + a.add_bond() + """ + # Create interface 'BondEthernetX' + create_args = { + 'id': self.instance, + 'mode': self.mode, + 'lb': self.load_balance, + } + if self.mac: + create_args.update({'use_custom_mac': True, 'mac_address': self.mac}) + self.vpp.api.bond_create2(**create_args) + # Add LCP pair (kernel) interface + self.kernel_add() + # Set interface state + self.set_state(self.state) + self.set_admin_state(self.state) + self.index = self.vpp.get_sw_if_index(self.vpp_ifname) + + def delete_bond(self): + """Delete Bond interface + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = VPPBondInterface(ifname='vppbond0', config) + a.delete_bond() + """ + self.vpp.api.bond_delete(sw_if_index=self.index) + + def add_member(self, interface): + """Add member to Bond interface + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = VPPBondInterface(ifname='vppbond0', config) + a.add_member(interface='eth0') + """ + member_if_index = self.vpp.get_sw_if_index(interface) + self.vpp.api.bond_add_member( + bond_sw_if_index=self.index, sw_if_index=member_if_index + ) + self.vpp.api.sw_interface_set_promisc( + sw_if_index=member_if_index, promisc_on=True + ) + + def detach_member(self, interface): + """Detach member from Bond interface + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = VPPBondInterface(ifname='vppbond0') + a.detach_member(interface='eth0') + """ + member_if_index = self.vpp.get_sw_if_index(interface) + self.vpp.api.bond_detach_member(sw_if_index=member_if_index) + + def get_members(self): + members = [] + tmp = self.vpp.api.sw_member_interface_dump(sw_if_index=self.index) + for member in tmp: + members.append(member.interface_name) + return members + + def kernel_add(self): + """Add LCP pair + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = VPPBondInterface(ifname='vppbond0') + a.kernel_add() + """ + self.vpp.lcp_pair_add(self.vpp_ifname, self.ifname) + + def kernel_delete(self): + """Delete LCP pair + Example: + from vyos.ifconfig.vpp import VPPBondInterface + a = VPPBondInterface(ifname='vppbond0') + a.kernel_delete() + """ + self.vpp.lcp_pair_del(self.vpp_ifname, self.ifname) + + def remove(self): + if self.index: + # Detach all existing members + members = self.get_members() + for member in members: + self.detach_member(interface=member) + + # Delete lcp pair interface + if self.vpp.lcp_pair_find(vpp_name_hw=self.vpp_ifname): + self.kernel_delete() + + # Delete bonding interface + self.delete_bond() + + def update(self, config): + # Add bond interface + self.add_bond() + + # Add members to bond + for member in config.get('member', {}).get('interface', []): + self.add_member(interface=member) + + # Set rx-mode + rx_mode = config.get('vpp_settings', {}).get('interface_rx_mode') + if rx_mode: + self.set_rx_mode(rx_mode) + + # Apply all settings to the lcp pair (kernel) interface + super().update(config) diff --git a/python/vyos/ifconfig/vpp/interface.py b/python/vyos/ifconfig/vpp/interface.py new file mode 100644 index 000000000..1b87af4d2 --- /dev/null +++ b/python/vyos/ifconfig/vpp/interface.py @@ -0,0 +1,56 @@ +# +# Copyright (C) VyOS Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +from vyos.vpp import VPPControl + + +class VPPInterface: + def __init__(self, vpp_ifname): + self.vpp_ifname = vpp_ifname + self.vpp = VPPControl() + + def set_state(self, state: str): + """Set interface state to UP or DOWN + Args: + state (str): The state of the interface. Options are 'up' and 'down'. + Example: + from vyos.interface.vpp import VPPInterface + a = VPPInterface(vpp_ifname='eth0') + a.set_state(state='up') + """ + if state not in ['up', 'down']: + raise ValueError(f"Invalid state: {state}") + state_flag = 1 if state == 'up' else 0 + if_index = self.vpp.get_sw_if_index(self.vpp_ifname) + self.vpp.api.sw_interface_set_flags(sw_if_index=if_index, flags=state_flag) + + def get_state(self): + """Get interface state + Example: + from vyos.interface.vpp import VPPInterface + a = VPPInterface(vpp_ifname='eth0') + a.get_state() + """ + if_index = self.vpp.get_sw_if_index(self.vpp_ifname) + return self.vpp.api.sw_interface_dump(sw_if_index=if_index)[0]['flags'] + + def set_rx_mode(self, rx_mode): + lcp_pair = self.vpp.lcp_pair_find(vpp_name_hw=self.vpp_ifname) + if lcp_pair: + lcp_name = lcp_pair.get('vpp_name_kernel') + if lcp_name: + self.vpp.iface_rxmode(lcp_name, rx_mode) diff --git a/python/vyos/vpp/interface/__init__.py b/python/vyos/vpp/interface/__init__.py index 903b7cbfc..c54e5ca60 100644 --- a/python/vyos/vpp/interface/__init__.py +++ b/python/vyos/vpp/interface/__init__.py @@ -15,7 +15,6 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -from .bond import BondInterface from .bridge import BridgeInterface from .ethernet import EthernetInterface from .geneve import GeneveInterface @@ -28,7 +27,6 @@ from .wireguard import WireguardInterface from .xconnect import XconnectInterface __all__ = [ - 'BondInterface', 'BridgeInterface', 'EthernetInterface', 'GeneveInterface', diff --git a/python/vyos/vpp/interface/bond.py b/python/vyos/vpp/interface/bond.py deleted file mode 100644 index abfcf5d0d..000000000 --- a/python/vyos/vpp/interface/bond.py +++ /dev/null @@ -1,122 +0,0 @@ -# -# Copyright (C) VyOS Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program; if not, write to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -from vyos.vpp.control_host import set_promisc -from vyos.vpp.interface.interface import Interface - - -class BondInterface(Interface): - def __init__( - self, - ifname, - mode: str = '', - load_balance: int = 0, - mac: str = '', - kernel_interface: str = '', - state: str = 'up', - ): - super().__init__(ifname) - self.instance = int(ifname.removeprefix('bond')) - self.ifname = f'BondEthernet{self.instance}' - self.mode = mode - self.load_balance = load_balance - self.mac = mac - self.kernel_interface = kernel_interface - self.state = state - - def add(self): - """Create Bond interface - https://github.com/FDio/vpp/blob/stable/2306/src/vnet/bonding/bond.api - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0', mode=5) - a.add() - """ - # Create interface 'bondX' - create_args = { - 'id': self.instance, - 'mode': self.mode, - 'lb': self.load_balance, - } - if self.mac: - create_args.update({'use_custom_mac': True, 'mac_address': self.mac}) - self.vpp.api.bond_create2(**create_args) - if self.kernel_interface: - self.vpp.lcp_pair_add(self.ifname, self.kernel_interface) - # Set interface state - self.set_state(self.state) - - def delete(self): - """Delete Bond interface - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0') - a.delete() - """ - bond_if_index = self.vpp.get_sw_if_index(self.ifname) - self.vpp.api.bond_delete(sw_if_index=bond_if_index) - - def add_member(self, interface): - """Add member to Bond interface - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0') - a.add_member(interface='eth0') - """ - bond_if_index = self.vpp.get_sw_if_index(f'BondEthernet{self.instance}') - member_if_index = self.vpp.get_sw_if_index(interface) - member_if_type = self.vpp.get_sw_if_dev_type(interface) - self.vpp.api.bond_add_member( - bond_sw_if_index=bond_if_index, sw_if_index=member_if_index - ) - self.vpp.api.sw_interface_set_promisc( - sw_if_index=member_if_index, promisc_on=True - ) - if member_if_type == 'AF_XDP interface': - set_promisc(f'defunct_{interface}', 'on') - - def detach_member(self, interface): - """Detach member from Bond interface - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0') - a.detach_member(interface='eth0') - """ - member_if_index = self.vpp.get_sw_if_index(interface) - self.vpp.api.bond_detach_member(sw_if_index=member_if_index) - - def kernel_add(self): - """Add LCP pair - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0', mode=5) - a.kernel_add() - """ - self.vpp.lcp_pair_add(self.ifname, self.kernel_interface) - - def kernel_delete(self): - """Delete LCP pair - Example: - from vyos.vpp.interface import BondInterface - a = BondInterface(ifname='bond0', mode=5) - a.kernel_delete() - """ - self.vpp.lcp_pair_del(self.ifname, self.kernel_interface) - - def lcp_pair_exists(self): - """Check if LCP pair exists""" - return bool(self.vpp.lcp_pair_find(self.kernel_interface)) diff --git a/python/vyos/vpp/utils.py b/python/vyos/vpp/utils.py index 0c247e48a..5ae4cd296 100644 --- a/python/vyos/vpp/utils.py +++ b/python/vyos/vpp/utils.py @@ -58,9 +58,9 @@ def vpp_iface_name_transform(iface: str) -> str: str: Interface name formatted as recognized by VPP (e.g., "BondEthernet0"). """ vpp_iface_name = iface - if vpp_iface_name.startswith('bond'): + if vpp_iface_name.startswith('vppbond'): # interface name in VPP is BondEthernetX - vpp_iface_name = vpp_iface_name.replace('bond', 'BondEthernet') + vpp_iface_name = vpp_iface_name.replace('vppbond', 'BondEthernet') return vpp_iface_name |
