Skip to content

Instantly share code, notes, and snippets.

@mtXTJocj
Created December 14, 2020 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mtXTJocj/056f52f93e94aba7f87dd842eac9f6f9 to your computer and use it in GitHub Desktop.
Save mtXTJocj/056f52f93e94aba7f87dd842eac9f6f9 to your computer and use it in GitHub Desktop.
{
"Nodes": {
"helloworld":{}
}
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0": {
"ipv4_address": "192.0.2.1/24"
}
}
},
"ns2":{
"interfaces": {
"ns2-veth0": {
"ipv4_address": "192.0.2.2/24"
}
}
}
},
"Links": [
[["ns1", "ns1-veth0"], ["ns2", "ns2-veth0"]]
]
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0":{
"ipv4_address": "192.0.2.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"192.0.2.254"
}
]
},
"ns2":{
"interfaces": {
"ns2-veth0":{
"ipv4_address": "198.51.100.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"198.51.100.254"
}
]
},
"router":{
"interfaces": {
"gw-veth0":{
"ipv4_address": "192.0.2.254/24"
},
"gw-veth1":{
"ipv4_address": "198.51.100.254/24"
}
}
}
},
"Links": [
[["ns1", "ns1-veth0"], ["router", "gw-veth0"]],
[["ns2", "ns2-veth0"], ["router", "gw-veth1"]]
]
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0":{
"ipv4_address": "192.0.2.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"192.0.2.254"
}
]
},
"ns2":{
"interfaces": {
"ns2-veth0":{
"ipv4_address": "198.51.100.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"198.51.100.254"
}
]
},
"router1":{
"interfaces": {
"gw1-veth0":{
"ipv4_address": "192.0.2.254/24"
},
"gw1-veth1":{
"ipv4_address": "203.0.113.1/24"
}
},
"routes":[
{
"dst":"198.51.100.0/24",
"via":"203.0.113.2"
}
],
"ipv4_forward": true
},
"router2":{
"interfaces": {
"gw2-veth0":{
"ipv4_address": "203.0.113.2/24"
},
"gw2-veth1":{
"ipv4_address": "198.51.100.254/24"
}
},
"routes":[
{
"dst":"192.0.2.0/24",
"via":"203.0.113.1"
}
],
"ipv4_forward": true
}
},
"Links": [
[["ns1", "ns1-veth0"], ["router1", "gw1-veth0"]],
[["router1", "gw1-veth1"], ["router2", "gw2-veth0"]],
[["router2", "gw2-veth1"], ["ns2", "ns2-veth0"]]
]
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0": {
"ipv4_address": "192.0.2.1/24",
"mac_address": "00:00:5E:00:53:01"
}
}
},
"ns2":{
"interfaces": {
"ns2-veth0": {
"ipv4_address": "192.0.2.2/24",
"mac_address": "00:00:5E:00:53:02"
}
}
}
},
"Links": [
[["ns1", "ns1-veth0"], ["ns2", "ns2-veth0"]]
]
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0": {
"mac_address": "00:00:5E:00:53:11",
"ipv4_address": "192.0.2.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"192.0.2.254"
}
]
},
"ns2":{
"interfaces": {
"ns2-veth0": {
"mac_address": "00:00:5E:00:53:22",
"ipv4_address": "198.51.100.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"198.51.100.254"
}
]
},
"gw":{
"interfaces": {
"gw-veth0": {
"mac_address": "00:00:5E:00:53:12",
"ipv4_address": "192.0.2.254/24"
},
"gw-veth1": {
"mac_address": "00:00:5E:00:53:21",
"ipv4_address": "198.51.100.254/24"
}
},
"ipv4_forward": true
}
},
"Links": [
[["ns1", "ns1-veth0"], ["gw", "gw-veth0"]],
[["ns2", "ns2-veth0"], ["gw", "gw-veth1"]]
]
}
{
"Nodes": {
"ns1":{
"interfaces": {
"ns1-veth0": {
"ipv4_address": "192.0.2.1/24",
"mac_address": "00:00:5E:00:53:01"
}
}
},
"ns2":{
"interfaces": {
"ns2-veth0": {
"ipv4_address": "192.0.2.2/24",
"mac_address": "00:00:5E:00:53:02"
}
}
},
"ns3":{
"interfaces": {
"ns3-veth0": {
"ipv4_address": "192.0.2.3/24",
"mac_address": "00:00:5E:00:53:03"
}
}
},
"br0":{
"node_type": "Bridge",
"interfaces": {
"ns1-br0": {},
"ns2-br0": {},
"ns3-br0": {}
}
}
},
"Links": [
[["ns1", "ns1-veth0"], ["br0", "ns1-br0"]],
[["ns2", "ns2-veth0"], ["br0", "ns2-br0"]],
[["ns3", "ns3-veth0"], ["br0", "ns3-br0"]]
]
}
{
"Nodes": {
"server":{
"interfaces": {
"s-veth0": {
"ipv4_address": "192.0.2.254/24"
}
}
},
"client":{
"interfaces": {
"c-veth0": {
}
}
}
},
"Links": [
[["server", "s-veth0"], ["client", "c-veth0"]]
]
}
{
"Nodes": {
"lan":{
"interfaces":{
"lan-veth0": {
"node_name": "lan",
"ipv4_address": "192.0.2.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"192.0.2.254"
}
]
},
"router":{
"interfaces": {
"gw-veth0": {
"node_name": "router",
"ipv4_address": "192.0.2.254/24"
},
"gw-veth1": {
"node_name": "router",
"ipv4_address": "203.0.113.254/24"
}
}
},
"wan": {
"interfaces": {
"wan-veth0": {
"node_name": "wan",
"ipv4_address": "203.0.113.1/24"
}
},
"routes":[
{
"dst":"default",
"via":"203.0.113.254"
}
]
}
},
"Links": [
[["lan", "lan-veth0"], ["router", "gw-veth0"]],
[["router", "gw-veth1"], ["wan", "wan-veth0"]]
]
}
import json
import subprocess as sp
import sys
def _run_command(cmd):
print(' '.join(cmd))
sp.run(cmd)
class Node(object):
def __init__(self, name: str, interfaces={}, routes=[], ipv4_forward=True, **_):
super(Node, self).__init__()
self.name = name
self.routes = routes
self.interfaces = {k: NetInterface(k, self, **v)
for k, v in interfaces.items()}
self.ipv4_forward = ipv4_forward
def create_command(self):
cmd = ['sudo', 'ip', 'netns', 'add', self.name]
_run_command(cmd)
if self.ipv4_forward:
cmd = ['sudo', 'ip', 'netns', 'exec',
self.name, 'sysctl', 'net.ipv4.ip_forward=1']
_run_command(cmd)
def remove_command(self):
cmd = ['sudo', 'ip', 'netns', 'delete', self.name]
_run_command(cmd)
def add_interface(self, if_name: str):
cmd = ['sudo', 'ip', 'link', 'set', if_name, 'netns', self.name]
_run_command(cmd)
cmd = ['sudo', 'ip', 'netns', 'exec', self.name,
'ip', 'link', 'set', if_name, 'up']
_run_command(cmd)
def set_route(self):
for r in self.routes:
dst = r['dst']
via = r['via']
cmd = ['sudo', 'ip', 'netns', 'exec',
self.name, 'ip', 'route', 'add', dst, 'via', via]
_run_command(cmd)
class Bridge(object):
def __init__(self, name: str, interfaces={}, **_):
super(Bridge, self).__init__()
self.name = name
self.interfaces = {k: NetInterface(k, self, **v)
for k, v in interfaces.items()}
def create_command(self):
cmd = ['sudo', 'ip', 'link', 'add', 'dev', self.name, 'type', 'bridge']
_run_command(cmd)
cmd = ['sudo', 'ip', 'link', 'set', self.name, 'up']
_run_command(cmd)
def remove_command(self):
cmd = ['sudo', 'ip', 'link', 'delete', self.name]
_run_command(cmd)
def add_interface(self, if_name: str):
cmd = ['sudo', 'ip', 'link', 'set', if_name, 'master', self.name]
_run_command(cmd)
cmd = ['sudo', 'ip', 'link', 'set', if_name, 'up']
_run_command(cmd)
def set_route(self):
pass
def create_node(name: str, node_type: str = "Node", **kargs):
cls = getattr(sys.modules[__name__], node_type)
return cls(name, **kargs)
class NetInterface(object):
def __init__(self, name: str, node, ipv4_address: str = None, mac_address: str = None, **_):
super(NetInterface, self).__init__()
self.name = name
self.node = node
self.ipv4_address = ipv4_address
self.mac_address = mac_address
def create_command(self):
self.node.add_interface(self.name)
if self.ipv4_address:
cmd = ['sudo', 'ip', 'netns', 'exec', self.node.name, 'ip',
'address', 'add', self.ipv4_address, 'dev', self.name]
_run_command(cmd)
if self.mac_address:
cmd = ['sudo', 'ip', 'netns', 'exec', self.node.name,
'ip', 'link', 'set', 'dev', self.name, 'address', self.mac_address]
_run_command(cmd)
class Link(object):
def __init__(self, if0: NetInterface, if1: NetInterface):
super(Link, self).__init__()
self.if0 = if0
self.if1 = if1
def create_command(self):
cmd = ['sudo', 'ip', 'link', 'add', self.if0.name,
'type', 'veth', 'peer', 'name', self.if1.name]
_run_command(cmd)
self.if0.create_command()
self.if1.create_command()
def create_network(j):
nodes = {}
def _get_node(name: str, **kwargs):
if name in nodes:
return nodes[name]
node = create_node(name, **kwargs)
node.create_command()
nodes[name] = node
return node
nodes = {}
for k, v in j['Nodes'].items():
nodes[k] = _get_node(k, **v)
if 'Links' in j:
for if0, if1 in j['Links']:
node_name0, if_name0 = if0
node_name1, if_name1 = if1
node0 = _get_node(node_name0)
node1 = _get_node(node_name1)
if0 = node0.interfaces[if_name0]
if1 = node1.interfaces[if_name1]
l = Link(if0, if1)
l.create_command()
for n in nodes.values():
n.set_route()
def clean_network(j):
for k, v in j['Nodes'].items():
node = create_node(k, **v)
node.remove_command()
def print_usage(prog_name):
print(prog_name, ': json start|stop')
exit(0)
if len(sys.argv) < 3:
print_usage(sys.argv[0])
with open(sys.argv[1], "r") as f:
j = json.load(f)
if sys.argv[2] == 'start':
create_network(j)
elif sys.argv[2] == 'stop':
clean_network(j)
else:
print_usage(sys.argv[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment