def new_iface(self, net: CoreNetworkBase, iface_data: InterfaceData) -> CoreInterface: logging.info("creating interface") ips = iface_data.get_ips() iface_id = iface_data.id if iface_id is None: iface_id = self.next_iface_id() name = iface_data.name if name is None: name = f"gt{iface_id}" if self.up: # this is reached when this node is linked to a network node # tunnel to net not built yet, so build it now and adopt it _, remote_tap = self.session.distributed.create_gre_tunnel( net, self.server) self.adopt_iface(remote_tap, iface_id, iface_data.mac, ips) return remote_tap else: # this is reached when configuring services (self.up=False) iface = GreTap(node=self, name=name, session=self.session, start=False) self.adopt_iface(iface, iface_id, iface_data.mac, ips) return iface
def new_iface(self, net: "CoreNetworkBase", iface_data: InterfaceData) -> CoreInterface: """ Create a new network interface. :param net: network to associate with :param iface_data: interface data for new interface :return: interface index """ with self.lock: if net.has_custom_iface: return net.custom_iface(self, iface_data) else: iface_id = iface_data.id if iface_id is not None and iface_id in self.ifaces: raise CoreError( f"node({self.name}) already has interface({iface_id})") iface_id = self.newveth(iface_id, iface_data.name, iface_data.mtu) self.attachnet(iface_id, net) if iface_data.mac: self.set_mac(iface_id, iface_data.mac) for ip in iface_data.get_ips(): self.add_ip(iface_id, ip) self.ifup(iface_id) return self.get_iface(iface_id)
def new_iface(self, net: CoreNetworkBase, iface_data: InterfaceData) -> CoreInterface: """ 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 iface_data: interface data for new interface :return: interface index :raises ValueError: when an interface has already been created, one max """ with self.lock: iface_id = iface_data.id if iface_id is None: iface_id = 0 if self.iface.net is not None: raise CoreError( "RJ45 nodes support at most 1 network interface") self.ifaces[iface_id] = self.iface self.iface_id = iface_id if net is not None: self.iface.attachnet(net) for ip in iface_data.get_ips(): self.add_ip(ip) return self.iface
def test_node_set_mac_exception(self, session: Session, mac: str): # given node = session.add_node(CoreNode) switch = session.add_node(SwitchNode) iface_data = InterfaceData() iface = node.new_iface(switch, iface_data) # when with pytest.raises(CoreError): node.set_mac(iface.node_id, mac)
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build CORE API TLVs for a point-to-point link. One Link message describes this network. :param flags: message flags :return: list of link data """ all_links = [] if len(self.ifaces) != 2: return all_links ifaces = self.get_ifaces() iface1 = ifaces[0] iface2 = ifaces[1] unidirectional = 0 if iface1.local_options == iface2.local_options else 1 iface1_data = iface1.get_data() iface2_data = iface2.get_data() link_data = LinkData( message_type=flags, type=self.linktype, node1_id=iface1.node.id, node2_id=iface2.node.id, iface1=iface1_data, iface2=iface2_data, options=iface1.local_options, ) link_data.options.unidirectional = unidirectional all_links.append(link_data) # build a 2nd link message for the upstream link parameters # (swap if1 and if2) if unidirectional: link_data = LinkData( message_type=MessageFlags.NONE, type=self.linktype, node1_id=iface2.node.id, node2_id=iface1.node.id, iface1=InterfaceData(id=iface2_data.id), iface2=InterfaceData(id=iface1_data.id), options=iface2.local_options, ) link_data.options.unidirectional = unidirectional all_links.append(link_data) return all_links
def test_node_add_ip_exception(self, session): # given node = session.add_node(CoreNode) switch = session.add_node(SwitchNode) iface_data = InterfaceData() iface = node.new_iface(switch, iface_data) ip = "256.168.0.1/24" # when with pytest.raises(CoreError): node.add_ip(iface.node_id, ip)
def test_node_set_mac(self, session: Session, mac: str, expected: str): # given node = session.add_node(CoreNode) switch = session.add_node(SwitchNode) iface_data = InterfaceData() iface = node.new_iface(switch, iface_data) # when node.set_mac(iface.node_id, mac) # then assert str(iface.mac) == expected
def setkey(self, key: int, iface_data: InterfaceData) -> None: """ Set the GRE key used for the GreTap device. This needs to be set prior to instantiating the GreTap device (before addrconfig). :param key: gre key :param iface_data: interface data for setting up tunnel key :return: nothing """ self.grekey = key ips = iface_data.get_ips() if ips: self.add_ips(ips)
def custom_iface(self, node: CoreNode, iface_data: InterfaceData) -> CoreInterface: # TUN/TAP is not ready for addressing yet; the device may # take some time to appear, and installing it into a # namespace after it has been bound removes addressing; # save addresses with the interface now iface_id = node.newtuntap(iface_data.id, iface_data.name) node.attachnet(iface_id, self) iface = node.get_iface(iface_id) iface.set_mac(iface_data.mac) for ip in iface_data.get_ips(): iface.add_ip(ip) if self.session.state == EventTypes.RUNTIME_STATE: self.session.emane.start_iface(self, iface) return iface
def test_node_add_ip(self, session: Session, ip: str, expected: str, is_ip6: bool): # given node = session.add_node(CoreNode) switch = session.add_node(SwitchNode) iface_data = InterfaceData() iface = node.new_iface(switch, iface_data) # when node.add_ip(iface.node_id, ip) # then if is_ip6: assert str(iface.get_ip6()) == expected else: assert str(iface.get_ip4()) == expected
def iface_to_data(iface: CoreInterface) -> InterfaceData: ip4 = iface.get_ip4() ip4_addr = str(ip4.ip) if ip4 else None ip4_mask = ip4.prefixlen if ip4 else None ip6 = iface.get_ip6() ip6_addr = str(ip6.ip) if ip6 else None ip6_mask = ip6.prefixlen if ip6 else None return InterfaceData( id=iface.node_id, name=iface.name, mac=str(iface.mac), ip4=ip4_addr, ip4_mask=ip4_mask, ip6=ip6_addr, ip6_mask=ip6_mask, )
def create_iface_data(iface_element: etree.Element) -> InterfaceData: iface_id = int(iface_element.get("id")) name = iface_element.get("name") mac = iface_element.get("mac") ip4 = iface_element.get("ip4") ip4_mask = get_int(iface_element, "ip4_mask") ip6 = iface_element.get("ip6") ip6_mask = get_int(iface_element, "ip6_mask") return InterfaceData( id=iface_id, name=name, mac=mac, ip4=ip4, ip4_mask=ip4_mask, ip6=ip6, ip6_mask=ip6_mask, )
def new_iface(self, net: "CoreNetworkBase", iface_data: InterfaceData) -> CoreInterface: """ Create a new network interface. :param net: network to associate with :param iface_data: interface data for new interface :return: interface index """ with self.lock: if net.has_custom_iface: return net.custom_iface(self, iface_data) else: iface_id = self.newveth(iface_data.id, iface_data.name) self.attachnet(iface_id, net) if iface_data.mac: self.set_mac(iface_id, iface_data.mac) for ip in iface_data.get_ips(): self.add_ip(iface_id, ip) self.ifup(iface_id) return self.get_iface(iface_id)
def link_iface(iface_proto: core_pb2.Interface) -> InterfaceData: """ Create interface data from interface proto. :param iface_proto: interface proto :return: interface data """ iface_data = None if iface_proto: name = iface_proto.name if iface_proto.name else None mac = iface_proto.mac if iface_proto.mac else None ip4 = iface_proto.ip4 if iface_proto.ip4 else None ip6 = iface_proto.ip6 if iface_proto.ip6 else None iface_data = InterfaceData( id=iface_proto.id, name=name, mac=mac, ip4=ip4, ip4_mask=iface_proto.ip4_mask, ip6=ip6, ip6_mask=iface_proto.ip6_mask, ) return iface_data
def get_data(self) -> InterfaceData: """ Retrieve the data representation of this interface. :return: interface data """ if self.node: iface_id = self.node.get_iface_id(self) else: iface_id = self.othernet.get_iface_id(self) data = InterfaceData(id=iface_id, name=self.name, mac=str(self.mac) if self.mac else None) ip4 = self.get_ip4() if ip4: data.ip4 = str(ip4.ip) data.ip4_mask = ip4.prefixlen ip6 = self.get_ip6() if ip6: data.ip6 = str(ip6.ip) data.ip6_mask = ip6.prefixlen return data
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build CORE API TLVs for a point-to-point link. One Link message describes this network. :param flags: message flags :return: list of link data """ all_links = [] if len(self.ifaces) != 2: return all_links ifaces = self.get_ifaces() iface1 = ifaces[0] iface2 = ifaces[1] unidirectional = 0 if iface1.getparams() != iface2.getparams(): unidirectional = 1 mac = str(iface1.mac) if iface1.mac else None iface1_data = InterfaceData(id=iface1.node.get_iface_id(iface1), name=iface1.name, mac=mac) ip4 = iface1.get_ip4() if ip4: iface1_data.ip4 = str(ip4.ip) iface1_data.ip4_mask = ip4.prefixlen ip6 = iface1.get_ip6() if ip6: iface1_data.ip6 = str(ip6.ip) iface1_data.ip6_mask = ip6.prefixlen mac = str(iface2.mac) if iface2.mac else None iface2_data = InterfaceData(id=iface2.node.get_iface_id(iface2), name=iface2.name, mac=mac) ip4 = iface2.get_ip4() if ip4: iface2_data.ip4 = str(ip4.ip) iface2_data.ip4_mask = ip4.prefixlen ip6 = iface2.get_ip6() if ip6: iface2_data.ip6 = str(ip6.ip) iface2_data.ip6_mask = ip6.prefixlen options_data = iface1.get_link_options(unidirectional) link_data = LinkData( message_type=flags, type=self.linktype, node1_id=iface1.node.id, node2_id=iface2.node.id, iface1=iface1_data, iface2=iface2_data, options=options_data, ) all_links.append(link_data) # build a 2nd link message for the upstream link parameters # (swap if1 and if2) if unidirectional: iface1_data = InterfaceData(id=iface2.node.get_iface_id(iface2)) iface2_data = InterfaceData(id=iface1.node.get_iface_id(iface1)) options_data = iface2.get_link_options(unidirectional) link_data = LinkData( message_type=MessageFlags.NONE, type=self.linktype, node1_id=iface2.node.id, node2_id=iface1.node.id, iface1=iface1_data, iface2=iface2_data, options=options_data, ) all_links.append(link_data) return all_links
def links(self, flags: MessageFlags = MessageFlags.NONE) -> List[LinkData]: """ Build link data objects for this network. Each link object describes a link between this network and a node. :param flags: message type :return: list of link data """ all_links = [] # build a link message from this network node to each node having a # connected interface for iface in self.get_ifaces(): uni = False linked_node = iface.node if linked_node is None: # two layer-2 switches/hubs linked together via linknet() if not iface.othernet: continue linked_node = iface.othernet if linked_node.id == self.id: continue iface.swapparams("_params_up") upstream_params = iface.getparams() iface.swapparams("_params_up") if iface.getparams() != upstream_params: uni = True unidirectional = 0 if uni: unidirectional = 1 mac = str(iface.mac) if iface.mac else None iface2_data = InterfaceData(id=linked_node.get_iface_id(iface), name=iface.name, mac=mac) ip4 = iface.get_ip4() if ip4: iface2_data.ip4 = str(ip4.ip) iface2_data.ip4_mask = ip4.prefixlen ip6 = iface.get_ip6() if ip6: iface2_data.ip6 = str(ip6.ip) iface2_data.ip6_mask = ip6.prefixlen options_data = iface.get_link_options(unidirectional) link_data = LinkData( message_type=flags, type=self.linktype, node1_id=self.id, node2_id=linked_node.id, iface2=iface2_data, options=options_data, ) all_links.append(link_data) if not uni: continue iface.swapparams("_params_up") options_data = iface.get_link_options(unidirectional) link_data = LinkData( message_type=MessageFlags.NONE, type=self.linktype, node1_id=linked_node.id, node2_id=self.id, options=options_data, ) iface.swapparams("_params_up") all_links.append(link_data) return all_links