Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit e20cf9f

Browse files
author
Jay Logue
authored
Merge pull request #382 from openweave/issue/more-simnet-fixes
Yet more fixes to simnet
2 parents e3daab3 + 5ef6e1e commit e20cf9f

File tree

2 files changed

+86
-40
lines changed

2 files changed

+86
-40
lines changed

src/tools/simnet/lib/simnet/layouts/two-devices.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@
3939
meshLocalPrefix = 'fd42:4242:4242::/64'
4040
)
4141

42-
LegacyThreadNetwork(
43-
name = 'legacy'
44-
)
45-
4642
#===============================================================================
4743
# Devices
4844
#===============================================================================
@@ -56,21 +52,21 @@
5652
isIP4DefaultGateway = True
5753
)
5854

59-
# Weave device with WiFi, Thread and Legacy Thread networks
55+
# Weave device with WiFi and Thread networks
6056
WeaveDevice(
6157
name = 'dev1',
6258
weaveNodeId = 1,
6359
weaveFabricId = 1,
6460
wifiNetwork = 'wifi',
6561
threadNetwork = 'thread',
66-
legacyNetwork = 'legacy',
62+
useLwIP = False
6763
)
6864

69-
# Weave device with Thread and Legacy Thread networks only
65+
# Weave device with Thread network only
7066
WeaveDevice(
7167
name = 'dev2',
7268
weaveFabricId = 1,
7369
weaveNodeId = 2,
7470
threadNetwork = 'thread',
75-
legacyNetwork = 'legacy'
71+
useLwIP = False
7672
)

src/tools/simnet/simnet.py

Lines changed: 82 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ def _buildNetwork(self):
350350

351351
# Create a virtual ethernet bridge to simulate the network
352352
addBridge(self.brName, nsName=self.nsName)
353+
354+
# Disable automatic address generation on the host interface for the bridge.
355+
setInterfaceAddressGenerationMode(self.brName, mode='none', nsName=self.nsName)
353356

354357
# Enable the host interface for the bridge
355358
enableInterface(self.brName, nsName=self.nsName)
@@ -953,7 +956,7 @@ def getLwIPConfig(self):
953956
lwipConfig = ''
954957
for i in self.interfaces:
955958
if isinstance(i, TapInterface):
956-
lwipConfig += i.getLwipConfig()
959+
lwipConfig += i.getLwIPConfig()
957960
if self.ip4DefaultGateway:
958961
lwipConfig += '--ip4-default-gw %s ' % self.ip4DefaultGateway
959962
if self.ip4DNSServers:
@@ -1167,7 +1170,7 @@ def __init__(self, name,
11671170

11681171
if wifiNetwork or wifiInterface:
11691172
if not wifiInterface:
1170-
wifiInterface = 'wifi' if not useLwIP else 'et0'
1173+
wifiInterface = 'wifi'
11711174
self.wifiInterface = self.addInterface(wifiNetwork, name=wifiInterface)
11721175
if not isinstance(self.wifiInterface.network, (WiFiNetwork, HostNetwork)):
11731176
raise ConfigException('Incompatible network %s attached to wifi interface of node %s' % (self.wifiInterface.network.name, name))
@@ -1176,7 +1179,7 @@ def __init__(self, name,
11761179

11771180
if threadNetwork or threadInterface:
11781181
if not threadInterface:
1179-
threadInterface = 'thread' if not useLwIP else 'th0'
1182+
threadInterface = 'thread'
11801183
self.threadInterface = self.addInterface(threadNetwork, name=threadInterface)
11811184
if not isinstance(self.threadInterface.network, (ThreadNetwork, HostNetwork)):
11821185
raise ConfigException('Incompatible network %s attached to thread interface of node %s' % (self.threadInterface.network.name, name))
@@ -1185,7 +1188,7 @@ def __init__(self, name,
11851188

11861189
if legacyNetwork or legacyInterface:
11871190
if not legacyInterface:
1188-
legacyInterface = 'legacy' if not useLwIP else 'al0'
1191+
legacyInterface = 'legacy'
11891192
self.legacyInterface = self.addInterface(legacyNetwork, name=legacyInterface)
11901193
if not isinstance(self.legacyInterface.network, (LegacyThreadNetwork, HostNetwork)):
11911194
raise ConfigException('Incompatible network %s attached to legacy thread interface of node %s' % (self.legacyInterface.network.name, name))
@@ -1194,7 +1197,7 @@ def __init__(self, name,
11941197

11951198
if cellularNetwork or cellularInterface:
11961199
if not cellularInterface:
1197-
cellularInterface = 'cell' if not useLwIP else 'cl0'
1200+
cellularInterface = 'cell'
11981201
self.cellularInterface = self.addInterface(cellularNetwork, name=cellularInterface)
11991202
if not isinstance(self.cellularInterface.network, (WiFiNetwork, Internet, HostNetwork)):
12001203
raise ConfigException('Incompatible network %s attached to cell interface of node %s' % (self.cellularInterface.network.name, name))
@@ -1365,7 +1368,6 @@ def __init__(self, node, network, name):
13651368
self.advertisedIP6Prefixes = []
13661369
self.ip4AutoConfig = None
13671370
self.ip6AutoConfig = None
1368-
self.isTapInterface = False
13691371

13701372
# Form a MAC address for the interface from the base MAC address, the node index and the interface index.
13711373
# Use a 48-bit or 64-bit MAC based on the nature of the connected network.
@@ -1439,15 +1441,15 @@ def buildInterface(self):
14391441
moveInterfaceToNamespace(tmpInterfaceName, nsName=self.node.nsName)
14401442
renameInterface(tmpInterfaceName, self.ifName, nsName=self.node.nsName)
14411443

1444+
# Disable automatic IPv6 link-local address generation on both interfaces. The peer interface
1445+
# doesn't need one, and one will be created for the node interface below.
1446+
setInterfaceAddressGenerationMode(self.ifName, mode='none', nsName=self.node.nsName)
1447+
setInterfaceAddressGenerationMode(self.peerIfName, mode='none', nsName=self.network.nsName)
1448+
14421449
# Enable the virtual interfaces.
14431450
enableInterface(self.ifName, nsName=self.node.nsName)
14441451
enableInterface(self.peerIfName, nsName=self.network.nsName)
14451452

1446-
# Flush any IPv6 link-local addresses automatically created by the network. The appropriate
1447-
# LL addresses will be added later (see below).
1448-
runCmd([ 'ip', '-6', 'addr', 'flush', 'dev', self.ifName, 'scope', 'link' ], nsName=self.node.nsName,
1449-
errMsg='Unable to flush IPv6 LL addresses on interface %s in namespace %s' % (self.ifName, self.node.nsName))
1450-
14511453
# Assign the IPv4 address to the node interface.
14521454
if self.ip4Address != None:
14531455
assignAddressToInterface(self.ifName, self.ip4Address, nsName=self.node.nsName)
@@ -1472,7 +1474,7 @@ def typeSummary(self):
14721474

14731475

14741476
class TapInterface(NodeInterface):
1475-
def __init__(self, node, network, name=None):
1477+
def __init__(self, node, network, name):
14761478

14771479
# If the node is implemented by the host, include the node index in the interface name to
14781480
# ensure it is unique.
@@ -1482,37 +1484,75 @@ def __init__(self, node, network, name=None):
14821484
# Initialize the base class.
14831485
NodeInterface.__init__(self, node, network, name)
14841486

1485-
# Form the name of the tap device from the node index and the name of the network to which it is attached.
1486-
self.tapDevName = namePrefix + network.name + '-' + str(node.nodeIndex)
1487+
self.tapBrName = namePrefix + 'tunbr-' + self.ifName
1488+
self.trunkIfName = namePrefix + 'trunk-' + self.ifName
1489+
self.peerIfName = namePrefix + str(network.networkIndex) + '-' + str(node.nodeIndex) + '-' + str(self.ifIndex)
14871490

14881491
def buildInterface(self):
14891492

1490-
# Create the tap device
1491-
# TODO: set owner and group
1492-
createTapInterface(self.tapDevName)
1493+
# Create a pair of virtual ethernet interfaces that will serve as a 'trunk' line between a bridge in the node's
1494+
# namespace and the bridge in the network's namespace.
1495+
# Use a temporary name for the first interface.
1496+
tmpInterfaceName = namePrefix + 'tmp-' + str(os.getpid()) + str(random.randint(0, 100))
1497+
createVETHPair(tmpInterfaceName, self.peerIfName)
1498+
1499+
# Assign the first trunk interface to the node namespace and rename it to the appropriate name.
1500+
if not self.node.isHostNode:
1501+
moveInterfaceToNamespace(tmpInterfaceName, nsName=self.node.nsName)
1502+
renameInterface(tmpInterfaceName, self.trunkIfName, nsName=self.node.nsName)
14931503

1494-
# Attach the tap interface to the network bridge.
1495-
moveInterfaceToNamespace(self.tapDevName, nsName=self.network.nsName)
1496-
attachInterfaceToBridge(self.tapDevName, self.network.brName, nsName=self.network.nsName)
1504+
# Attach the second trunk interface (the peer interface) to the network bridge.
1505+
moveInterfaceToNamespace(self.peerIfName, nsName=self.network.nsName)
1506+
attachInterfaceToBridge(self.peerIfName, self.network.brName, nsName=self.network.nsName)
14971507

1498-
# Enable the tap interface.
1499-
enableInterface(self.tapDevName, nsName=self.network.nsName)
1508+
# Create a bridge in the node namespace that will bridge between the tap device and the trunk
1509+
# interface.
1510+
addBridge(self.tapBrName, nsName=self.node.nsName)
1511+
1512+
# Attach the first trunk interface to the TAP bridge.
1513+
attachInterfaceToBridge(self.trunkIfName, self.tapBrName, nsName=self.node.nsName)
1514+
1515+
# Create a tap device in the node namespace.
1516+
user = os.environ['SUDO_USER']
1517+
createTapInterface(self.ifName, user=user, group=user, nsName=self.node.nsName)
1518+
1519+
# Attach the tap interface to the TAP bridge.
1520+
attachInterfaceToBridge(self.ifName, self.tapBrName, nsName=self.node.nsName)
1521+
1522+
# Disable automatic address generation on all associated interfaces.
1523+
setInterfaceAddressGenerationMode(self.ifName, mode='none', nsName=self.node.nsName)
1524+
setInterfaceAddressGenerationMode(self.tapBrName, mode='none', nsName=self.node.nsName)
1525+
setInterfaceAddressGenerationMode(self.trunkIfName, mode='none', nsName=self.node.nsName)
1526+
setInterfaceAddressGenerationMode(self.peerIfName, mode='none', nsName=self.network.nsName)
1527+
1528+
# Enable the interfaces.
1529+
enableInterface(self.tapBrName, nsName=self.node.nsName)
1530+
enableInterface(self.trunkIfName, nsName=self.node.nsName)
1531+
enableInterface(self.peerIfName, nsName=self.network.nsName)
1532+
enableInterface(self.ifName, nsName=self.node.nsName)
15001533

15011534
def clearInterface(self):
15021535

15031536
# Delete the tap device.
1504-
deleteInterface(self.tapDevName, nsName=self.network.nsName)
1537+
deleteInterface(self.ifName, nsName=self.node.nsName)
1538+
1539+
# Delete the trunk and peer interfaces.
1540+
deleteInterface(self.trunkIfName, nsName=self.node.nsName)
1541+
deleteInterface(self.peerIfName, nsName=self.network.nsName)
1542+
1543+
# Delete the TAP bridge.
1544+
deleteBridge(self.tapBrName, nsName=self.node.nsName)
15051545

15061546
def typeSummary(self):
1507-
return 'tap device connected to network "%s" via interface %s' % (self.network.name, self.tapDevName)
1547+
return 'tap device "%s" connected to network "%s" via peer interface %s' % (self.ifName, self.network.name, self.peerIfName)
15081548

15091549
def getLwIPConfig(self):
1510-
lwipConfig = '--%s-tap-device %s ' % (i.ifName, i.tapDevName)
1511-
lwipConfig += '--%s-mac-addr %012X ' % (i.ifName, i.macAddress) # TODO: handle case where MAC is 64-bits
1512-
if i.ip4Enabled and i.ip4Address:
1513-
lwipConfig += '--%s-ip4-addr %s ' % (i.ifName, i.ip4Address)
1514-
if i.ip6Enabled and len(i.ip6Addresses) > 0:
1515-
lwipConfig += '--%s-ip6-addrs %s ' % (i.ifName, ','.join([ str(a) for a in i.ip6Addresses ]))
1550+
lwipConfig = '--%s-tap-device %s ' % (self.ifName, self.ifName)
1551+
lwipConfig += '--%s-mac-addr %012X ' % (self.ifName, self.macAddress) # TODO: handle case where MAC is 64-bits
1552+
if self.ip4Enabled and self.ip4Address:
1553+
lwipConfig += '--%s-ip4-addr %s ' % (self.ifName, self.ip4Address)
1554+
if self.ip6Enabled and len(self.ip6Addresses) > 0:
1555+
lwipConfig += '--%s-ip6-addrs %s ' % (self.ifName, ','.join([ str(a) for a in self.ip6Addresses ]))
15161556
return lwipConfig;
15171557

15181558

@@ -1687,8 +1727,8 @@ def createVETHPair(name, peerName):
16871727
runCmd([ 'ip', 'link', 'add', 'name', name, 'type', 'veth', 'peer', 'name', peerName ], errMsg='Unable to create virtual ethernet interface pair %s' % (name))
16881728
time.sleep(0.01)
16891729

1690-
def createTapInterface(name, user='root', group='root'):
1691-
runCmd([ 'tunctl', '-u', user, '-g', group, '-t', name], errMsg='Unable to create tap interface pair %s' % (name))
1730+
def createTapInterface(name, user='root', group='root', nsName=None):
1731+
runCmd([ 'tunctl', '-u', user, '-g', group, '-t', name], errMsg='Unable to create tap interface pair %s' % (name), nsName=nsName)
16921732

16931733
def moveInterfaceToNamespace(ifName, nsName=None):
16941734
runCmd([ 'ip', 'link', 'set', ifName, 'netns', nsName ], errMsg='Unable to assign virtual ethernet interface %s to namespace %s' % (ifName, nsName))
@@ -1718,6 +1758,16 @@ def attachInterfaceToBridge(ifName, brName, nsName=None):
17181758
runCmd([ 'brctl', 'addif', brName, ifName ], nsName=nsName,
17191759
errMsg='Unable to assign virtual ethernet interface %s to bridge %s' % (ifName, brName))
17201760

1761+
def flushLinkLocalAddresses(ifName, nsName=None):
1762+
# Flush any IPv6 link-local addresses automatically created by the system.
1763+
runCmd([ 'ip', '-6', 'addr', 'flush', 'dev', ifName, 'scope', 'link' ], nsName=nsName,
1764+
errMsg='Unable to flush IPv6 LL addresses on interface %s in namespace %s' % (ifName, nsName))
1765+
1766+
def setInterfaceAddressGenerationMode(ifName, mode, nsName=None):
1767+
# Set the IPv6 address generation mode for the interface.
1768+
runCmd([ 'ip', 'link', 'set', 'dev', ifName, 'addrgenmode', mode ], nsName=nsName,
1769+
errMsg='Unable to set the IPv6 address generation mode on interface %s in namespace %s' % (ifName, nsName))
1770+
17211771
def getInterfaces(nsName=None):
17221772
out = runCmd([ 'ip', '-o', 'link', 'show' ], errMsg='Failed to enumerate interfaces', nsName=nsName)
17231773
out = out.replace('\\', '') # move backslashes introduced by -o

0 commit comments

Comments
 (0)