Last active
July 17, 2019 04:10
-
-
Save maxam2017/09358b5c820631c1ab231b2083711781 to your computer and use it in GitHub Desktop.
Segment Routing with flexible N*M leaf-spine topology
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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