def addaddr(self, addr): """ Add address to to network interface. :param str addr: address to add :return: nothing :raises CoreCommandError: when there is a command exception """ if self.up: self.net_client.create_address(self.name, str(addr)) CoreInterface.addaddr(self, addr)
def addaddr(self, addr: str) -> None: """ Add address to to network interface. :param addr: address to add :return: nothing :raises CoreCommandError: when there is a command exception """ addr = utils.validate_ip(addr) if self.up: self.net_client.create_address(self.name, addr) CoreInterface.addaddr(self, addr)
def addaddr(self, addr): """ Add address to to network interface. :param str addr: address to add :return: nothing :raises CoreCommandError: when there is a command exception """ if self.up: utils.check_cmd( [constants.IP_BIN, "addr", "add", str(addr), "dev", self.name]) CoreInterface.addaddr(self, addr)
class Rj45Node(CoreNodeBase): """ RJ45Node is a physical interface on the host linked to the emulated network. """ apitype: NodeTypes = NodeTypes.RJ45 type: str = "rj45" def __init__( self, session: "Session", _id: int = None, name: str = None, mtu: int = 1500, start: bool = True, server: DistributedServer = None, ) -> None: """ Create an RJ45Node instance. :param session: core session instance :param _id: node id :param name: node name :param mtu: rj45 mtu :param start: start flag :param server: remote server node will run on, default is None for localhost """ super().__init__(session, _id, name, start, server) self.interface = CoreInterface(session, self, name, name, mtu, server) self.interface.transport_type = TransportType.RAW self.lock: threading.RLock = threading.RLock() self.ifindex: Optional[int] = None self.old_up: bool = False self.old_addrs: List[Tuple[str, Optional[str]]] = [] if start: self.startup() def startup(self) -> None: """ Set the interface in the up state. :return: nothing :raises CoreCommandError: when there is a command exception """ # interface will also be marked up during net.attach() self.savestate() self.net_client.device_up(self.interface.localname) self.up = True def shutdown(self) -> None: """ Bring the interface down. Remove any addresses and queuing disciplines. :return: nothing """ if not self.up: return localname = self.interface.localname self.net_client.device_down(localname) self.net_client.device_flush(localname) try: self.net_client.delete_tc(localname) except CoreCommandError: pass self.up = False self.restorestate() def newnetif(self, net: CoreNetworkBase, interface: InterfaceData) -> int: """ This is called when linking with another node. Since this node represents an interface, we do not create another object here, but attach ourselves to the given network. :param net: new network instance :param interface: interface data for new interface :return: interface index :raises ValueError: when an interface has already been created, one max """ with self.lock: ifindex = interface.id if ifindex is None: ifindex = 0 if self.interface.net is not None: raise ValueError( "RJ45 nodes support at most 1 network interface") self._netif[ifindex] = self.interface self.ifindex = ifindex if net is not None: self.interface.attachnet(net) for addr in interface.get_addresses(): self.addaddr(addr) return ifindex def delnetif(self, ifindex: int) -> None: """ Delete a network interface. :param ifindex: interface index to delete :return: nothing """ if ifindex is None: ifindex = 0 self._netif.pop(ifindex) if ifindex == self.ifindex: self.shutdown() else: raise ValueError(f"ifindex {ifindex} does not exist") def netif(self, ifindex: int, net: CoreNetworkBase = None) -> Optional[CoreInterface]: """ This object is considered the network interface, so we only return self here. This keeps the RJ45Node compatible with real nodes. :param ifindex: interface index to retrieve :param net: network to retrieve :return: a network interface """ if net is not None and net == self.interface.net: return self.interface if ifindex is None: ifindex = 0 if ifindex == self.ifindex: return self.interface return None def getifindex(self, netif: CoreInterface) -> Optional[int]: """ Retrieve network interface index. :param netif: network interface to retrieve index for :return: interface index, None otherwise """ if netif != self.interface: return None return self.ifindex def addaddr(self, addr: str) -> None: """ Add address to to network interface. :param addr: address to add :return: nothing :raises CoreCommandError: when there is a command exception """ addr = utils.validate_ip(addr) if self.up: self.net_client.create_address(self.name, addr) self.interface.addaddr(addr) def deladdr(self, addr: str) -> None: """ Delete address from network interface. :param addr: address to delete :return: nothing :raises CoreCommandError: when there is a command exception """ if self.up: self.net_client.delete_address(self.name, addr) self.interface.deladdr(addr) def savestate(self) -> None: """ Save the addresses and other interface state before using the interface for emulation purposes. TODO: save/restore the PROMISC flag :return: nothing :raises CoreCommandError: when there is a command exception """ self.old_up = False self.old_addrs: List[Tuple[str, Optional[str]]] = [] localname = self.interface.localname output = self.net_client.address_show(localname) for line in output.split("\n"): items = line.split() if len(items) < 2: continue if items[1] == f"{localname}:": flags = items[2][1:-1].split(",") if "UP" in flags: self.old_up = True elif items[0] == "inet": self.old_addrs.append((items[1], items[3])) elif items[0] == "inet6": if items[1][:4] == "fe80": continue self.old_addrs.append((items[1], None)) logging.info("saved rj45 state: addrs(%s) up(%s)", self.old_addrs, self.old_up) def restorestate(self) -> None: """ Restore the addresses and other interface state after using it. :return: nothing :raises CoreCommandError: when there is a command exception """ localname = self.interface.localname logging.info("restoring rj45 state: %s", localname) for addr in self.old_addrs: self.net_client.create_address(localname, addr[0], addr[1]) if self.old_up: self.net_client.device_up(localname) def setposition(self, x: float = None, y: float = None, z: float = None) -> None: """ Uses setposition from both parent classes. :param x: x position :param y: y position :param z: z position :return: True if position changed, False otherwise """ super().setposition(x, y, z) self.interface.setposition() def termcmdstring(self, sh: str) -> str: """ Create a terminal command string. :param sh: shell to execute command in :return: str """ raise NotImplementedError