Skip to content

Instantly share code, notes, and snippets.

@maxam2017
Last active July 17, 2019 04:10
Show Gist options
  • Save maxam2017/09358b5c820631c1ab231b2083711781 to your computer and use it in GitHub Desktop.
Save maxam2017/09358b5c820631c1ab231b2083711781 to your computer and use it in GitHub Desktop.
Segment Routing with flexible N*M leaf-spine topology
import argparse
import logging
import json
import subprocess
from requests import post, delete
from mininet.topo import Topo
from mininet.net import Mininet
from mininet.cli import CLI
from mininet.node import RemoteController, Host, OVSSwitch
from mininet.link import TCLink
#|-------------------
#| BASIC CONFIG |
#|-------------------
## parser
parser = argparse.ArgumentParser(
usage="Segment Routing Test[OVS part]",
description="Topology : N*N leaf-spine [created by Mininet]\nSegment routing: onos-netcfg",
formatter_class = argparse.RawTextHelpFormatter)
parser.add_argument("spine", help = "# of spine switch")
parser.add_argument("leaf", help = "# of leaf switch")
parser.add_argument("--host", help = "# of host", default=2)
parser.add_argument("--controller", help = "ip of controller", default='127.0.0.1')
args = parser.parse_args()
## logger
logging.basicConfig(level=logging.INFO)
logging.info(args)
#|---------------------------
#| MININET HOST CLASS |
#|---------------------------
class IpHost(Host):
def __init__(self, name, gateway, *args, **kwargs):
super(IpHost, self).__init__(name,*args,**kwargs)
self.gateway = gateway
def config(self, **kwargs):
Host.config(self,**kwargs)
mtu = "ifconfig " + self.name + "-eth0 mtu 1490"
self.cmd(mtu)
self.cmd('ip route add default via %s' % self.gateway)
#|---------------------------
#| NETWORK CONFIG |
#|---------------------------
netcfg = {
"ports":{},
"devices":{},
"hosts":{}
}
#|---------------------------
#| MININET TOPOLOGY |
#|---------------------------
class LeafSpine(Topo):
spineswitch = []
leafswitch = []
host = []
def __init__(self, spine, leaf, host):
Topo.__init__(self)
# add spine switch
for sid in range(1, spine+1):
name = 'Spine{}'.format(sid)
# using leftmost bit to clarify switch type
dpid = '0{:015x}'.format(sid)
partialMac = '{:010x}'.format(sid)
self.spineswitch.append(self.addSwitch(name, dpid=dpid))
netcfg["devices"]['of:{}'.format(dpid)] = {
"segmentrouting" : {
"name" : name,
"ipv4NodeSid" : '1{:03}'.format(sid),
"ipv4Loopback" : '10.6.{}.254'.format(leaf + sid),
"routerMac" : '{}:00'.format(':'.join(partialMac[i:i+2] for i in range(0,10,2))),
"isEdgeRouter" : False,
"adjacencySids" : []
},
"basic" : {
"name" : name,
"driver" : "ofdpa-ovs"
}
}
# add leaf switch
for lid in range(1, leaf+1):
name = 'Leaf{}'.format(lid)
dpid = '1{:015x}'.format(lid)
self.leafswitch.append(self.addSwitch(name, dpid=dpid))
lip = '10.6.{}.254'.format(lid)
partialMac = '{:010x}'.format(lid)
# lip is the gateway of those host below
netcfg["devices"]['of:{}'.format(dpid)] = {
"segmentrouting" : {
"name" : name,
"ipv4NodeSid" : '2{:03}'.format(lid),
"ipv4Loopback" : lip,
"routerMac" : '{}:01'.format(':'.join(partialMac[i:i+2] for i in range(0,10,2))),
"isEdgeRouter" : True,
"adjacencySids" : []
},
"basic" : {
"name" : name,
"driver" : "ofdpa-ovs"
}
}
# add host
for localhid in range(1, host+1):
hid = host * (lid - 1) + localhid
name = 'h{}'.format(hid)
mac = ':'.join('{:012x}'.format(hid)[i:i+2] for i in range(0,12,2))
hip = '10.6.{}.{}/24'.format(lid, localhid)
self.host.append(self.addHost(name, cls=IpHost, mac=mac , ip= hip, gateway=lip))
port = spine + localhid
netcfg["ports"]['of:{}/{}'.format(dpid,port)] = {
"interfaces": [
{
"ips": ['10.6.{}.254/24'.format(lid)],
"vlan-untagged": 20
}
]
}
netcfg["hosts"]['{}/-1'.format(mac)] = {
"basic": {
"ips": ['10.6.{}.{}'.format(lid, localhid)],
"locations": ['of:{}/{}'.format(dpid,port)]
}
}
for i in range(leaf):
for j in range(spine):
self.addLink(self.leafswitch[i],self.spineswitch[j])
for j in range(host):
self.addLink(self.leafswitch[i], self.host[i*host + j])
# topos = {'leaf-spine': (lambda: LeafSpine())}
#|---------------------------
#| MININET BUILD |
#|---------------------------
if __name__ == "__main__":
#ONOS_config
subprocess.call("curl -X POST -u onos:rocks 'http://localhost:8181/onos/v1/applications/org.onosproject.openflow/active'",shell=True)
subprocess.call("curl -X POST -u onos:rocks 'http://localhost:8181/onos/v1/applications/org.onosproject.segmentrouting/active'",shell=True)
subprocess.call("curl -X POST -u onos:rocks 'http://localhost:8181/onos/v1/applications/org.onosproject.netcfghostprovider/active'",shell=True)
subprocess.call("curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/v1/applications/org.onosproject.fwd/active'",shell=True)
topo = LeafSpine(int(args.spine), int(args.leaf), int(args.host))
file = open("netcfg.json", 'w')
file.write(json.dumps(netcfg))
file.close()
subprocess.call('~/onos/tools/package/runtime/bin/onos-netcfg {} netcfg.json'.format(args.controller),shell=True, executable="/bin/bash")
net = Mininet(topo=topo, link=TCLink, controller=None)
net.addController('c0', switch=OVSSwitch, controller=RemoteController, ip=args.controller, port=6653 )
net.start()
CLI(net)
net.stop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment