blob: 7229176a15625694eac8729610ab0448e48f5658 [file] [log] [blame]
Alexey Ivanovcc01a9c2019-01-16 09:50:46 -08001#!/usr/bin/python
Brenden Blancoaf956732015-06-09 13:58:42 -07002# Copyright (c) PLUMgrid, Inc.
3# Licensed under the Apache License, Version 2.0 (the "License")
4
Brenden Blancoc35989d2015-09-02 18:04:07 -07005from bcc import BPF
Brenden Blanco6bf723d2015-06-18 17:53:31 -07006from builtins import input
Brenden Blancoaf956732015-06-09 13:58:42 -07007from pyroute2 import IPRoute, NetNS, IPDB, NSPopen
8from random import shuffle
9from time import sleep
Brenden Blanco085379b2015-06-18 00:28:47 -070010from simulation import Simulation
Brenden Blancoaf956732015-06-09 13:58:42 -070011import sys
12
13ipr = IPRoute()
Brenden Blancoaf956732015-06-09 13:58:42 -070014ipdb = IPDB(nl=ipr)
15
Brenden Blanco6bf723d2015-06-18 17:53:31 -070016num_clients = 3
Brenden Blancoaf956732015-06-09 13:58:42 -070017num_vlans = 16
18
Brenden Blancoaf956732015-06-09 13:58:42 -070019# load the bpf program
Brenden Blanco085379b2015-06-18 00:28:47 -070020b = BPF(src_file="vlan_learning.c", debug=0)
Brenden Blancoaf956732015-06-09 13:58:42 -070021phys_fn = b.load_func("handle_phys2virt", BPF.SCHED_CLS)
22virt_fn = b.load_func("handle_virt2phys", BPF.SCHED_CLS)
23
Brenden Blancoc5462712015-06-12 14:07:04 -070024ingress = b.get_table("ingress")
25egress = b.get_table("egress")
Brenden Blancoaf956732015-06-09 13:58:42 -070026
Brenden Blanco085379b2015-06-18 00:28:47 -070027class VlanSimulation(Simulation):
28 def __init__(self, ipdb):
29 super(VlanSimulation, self).__init__(ipdb)
Brenden Blancoaf956732015-06-09 13:58:42 -070030
Brenden Blanco085379b2015-06-18 00:28:47 -070031 def start(self):
32 # start identical workers each in a namespace
Brenden Blanco6bf723d2015-06-18 17:53:31 -070033 for i in range(0, num_clients):
Brenden Blanco085379b2015-06-18 00:28:47 -070034 httpmod = ("SimpleHTTPServer" if sys.version_info[0] < 3
35 else "http.server")
36 cmd = ["python", "-m", httpmod, "80"]
37 self._create_ns("worker%d" % i, cmd=cmd, fn=virt_fn, action="drop",
38 ipaddr="172.16.1.5/24")
Brenden Blancoaf956732015-06-09 13:58:42 -070039
Brenden Blanco085379b2015-06-18 00:28:47 -070040 # simulate a physical eth vlan trunk
41 with self.ipdb.create(ifname="eth0a", kind="veth", peer="eth0b") as v:
42 v.up()
43 self.ipdb.interfaces.eth0b.up().commit()
Brenden Blancoaf956732015-06-09 13:58:42 -070044
Yonghong Song540d45a2015-07-22 10:17:39 -070045 # eth0a will be hooked to clients with vlan interfaces
46 # add the bpf program to eth0b for demuxing phys2virt packets
47 v = self.ipdb.interfaces["eth0b"]
48 ipr.tc("add", "ingress", v["index"], "ffff:")
49 ipr.tc("add-filter", "bpf", v["index"], ":1", fd=phys_fn.fd,
50 name=phys_fn.name, parent="ffff:", action="drop", classid=1)
Brenden Blancoaf956732015-06-09 13:58:42 -070051
Brenden Blanco085379b2015-06-18 00:28:47 -070052 # allocate vlans randomly
53 available_vlans = [i for i in range(2, 2 + num_vlans)]
54 shuffle(available_vlans)
Brenden Blanco6bf723d2015-06-18 17:53:31 -070055 available_ips = [[i for i in range(100, 105)] for i in range(0, num_clients)]
Brenden Blancoaf956732015-06-09 13:58:42 -070056
Brenden Blanco085379b2015-06-18 00:28:47 -070057 # these are simulations of physical clients
58 for i in range(0, num_clients):
Brenden Blanco085379b2015-06-18 00:28:47 -070059 macaddr = ("02:00:00:%.2x:%.2x:%.2x" %
60 ((i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff))
Brenden Blancoaf956732015-06-09 13:58:42 -070061
Brenden Blanco085379b2015-06-18 00:28:47 -070062 # assign this client to the given worker
Brenden Blanco6bf723d2015-06-18 17:53:31 -070063 idx = self.ipdb.interfaces["worker%da" % i]["index"]
Brenden Blanco085379b2015-06-18 00:28:47 -070064 mac = int(macaddr.replace(":", ""), 16)
Yonghong Song540d45a2015-07-22 10:17:39 -070065 ingress[ingress.Key(mac)] = ingress.Leaf(idx, 0, 0, 0, 0)
Brenden Blancoaf956732015-06-09 13:58:42 -070066
Brenden Blanco085379b2015-06-18 00:28:47 -070067 # test traffic with curl loop
68 cmd = ["bash", "-c",
69 "for i in {1..8}; do curl 172.16.1.5 -o /dev/null; sleep 1; done"]
Yonghong Song540d45a2015-07-22 10:17:39 -070070 client_ifc = self.ipdb.create(ifname="eth0a.%d" % i, kind="vlan",
71 link=self.ipdb.interfaces["eth0a"],
72 vlan_id=available_vlans.pop(0)).commit()
73 (out_ifc, in_ifc) = self._create_ns("client%d" % i, in_ifc=client_ifc,
Brenden Blanco6bf723d2015-06-18 17:53:31 -070074 ipaddr="172.16.1.100/24",
75 macaddr=macaddr, cmd=cmd)[1:3]
Brenden Blancoaf956732015-06-09 13:58:42 -070076
Brenden Blanco085379b2015-06-18 00:28:47 -070077try:
78 sim = VlanSimulation(ipdb)
79 sim.start()
80 sleep(10)
81 input("Press enter to exit: ")
Brenden Blancoaf956732015-06-09 13:58:42 -070082
Brenden Blanco085379b2015-06-18 00:28:47 -070083 stats_collect = {}
84 for key, leaf in ingress.items():
85 stats_collect[key.value] = [leaf.tx_pkts, leaf.tx_bytes, 0, 0]
86 for key, leaf in egress.items():
87 x = stats_collect.get(key.value, [0, 0, 0, 0])
88 x[2] = leaf.tx_pkts
89 x[3] = leaf.tx_bytes
90 for k, v in stats_collect.items():
91 print("mac %.12x rx pkts = %u, rx bytes = %u" % (k, v[0], v[1]))
92 print(" tx pkts = %u, tx bytes = %u" % (v[2], v[3]))
93finally:
94 if "eth0a" in ipdb.interfaces: ipdb.interfaces.eth0a.remove().commit()
Brenden Blanco085379b2015-06-18 00:28:47 -070095 if "sim" in locals(): sim.release()
96 ipdb.release()