Commit 950593b2 authored by Brenden Blanco's avatar Brenden Blanco

Merge pull request #94 from iovisor/weichunc_dev

full mesh vxlan example without multicast
parents a1655269 50f12423
...@@ -2,10 +2,16 @@ ...@@ -2,10 +2,16 @@
# Copyright (c) PLUMgrid, Inc. # Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License") # Licensed under the Apache License, Version 2.0 (the "License")
from sys import argv
from pyroute2 import IPRoute, NetNS, IPDB, NSPopen from pyroute2 import IPRoute, NetNS, IPDB, NSPopen
from simulation import Simulation from simulation import Simulation
from subprocess import PIPE from subprocess import PIPE
if len(argv) > 1 and argv[1] == "mesh":
multicast = 0
else:
multicast = 1
ipr = IPRoute() ipr = IPRoute()
ipdb = IPDB(nl=ipr) ipdb = IPDB(nl=ipr)
...@@ -24,7 +30,10 @@ class TunnelSimulation(Simulation): ...@@ -24,7 +30,10 @@ class TunnelSimulation(Simulation):
ipaddr = "172.16.1.%d/24" % (100 + i) ipaddr = "172.16.1.%d/24" % (100 + i)
host_info.append(self._create_ns("host%d" % i, ipaddr=ipaddr, host_info.append(self._create_ns("host%d" % i, ipaddr=ipaddr,
disable_ipv6=True)) disable_ipv6=True))
cmd = ["python", "tunnel.py"] if multicast:
cmd = ["python", "tunnel.py"]
else:
cmd = ["python", "tunnel_mesh.py", str(num_hosts), str(i)]
p = NSPopen(host_info[i][0].nl.netns, cmd, stdin=PIPE) p = NSPopen(host_info[i][0].nl.netns, cmd, stdin=PIPE)
self.processes.append(p) self.processes.append(p)
with self.ipdb.create(ifname="br-fabric", kind="bridge") as br: with self.ipdb.create(ifname="br-fabric", kind="bridge") as br:
......
// Copyright (c) PLUMgrid, Inc.
// Licensed under the Apache License, Version 2.0 (the "License")
#include <bcc/proto.h>
struct config {
int tunnel_ifindex;
};
BPF_TABLE("hash", int, struct config, conf, 1);
BPF_TABLE("hash", struct bpf_tunnel_key, int, tunkey2if, 1024);
BPF_TABLE("hash", int, struct bpf_tunnel_key, if2tunkey, 1024);
// Handle packets from the encap device, demux into the dest tenant
int handle_ingress(struct __sk_buff *skb) {
struct bpf_tunnel_key tkey = {};
bpf_skb_get_tunnel_key(skb, &tkey, sizeof(tkey));
int *ifindex = tunkey2if.lookup(&tkey);
if (ifindex) {
//bpf_trace_printk("ingress tunnel_id=%d remote_ip=%08x ifindex=%d\n",
// tkey.tunnel_id, tkey.remote_ipv4, *ifindex);
// mark from external
skb->tc_index = 1;
bpf_clone_redirect(skb, *ifindex, 1/*ingress*/);
} else {
bpf_trace_printk("ingress invalid tunnel_id=%d\n", tkey.tunnel_id);
}
return 1;
}
// Handle packets from the tenant, mux into the encap device
int handle_egress(struct __sk_buff *skb) {
int ifindex = skb->ifindex;
struct bpf_tunnel_key *tkey_p, tkey = {};
int one = 1;
struct config *cfg = conf.lookup(&one);
if (!cfg) return 1;
if (skb->tc_index) {
//bpf_trace_printk("from external\n");
// don't send it back out to encap device
return 1;
}
tkey_p = if2tunkey.lookup(&ifindex);
if (tkey_p) {
tkey.tunnel_id = tkey_p->tunnel_id;
tkey.remote_ipv4 = tkey_p->remote_ipv4;
bpf_skb_set_tunnel_key(skb, &tkey, sizeof(tkey));
bpf_clone_redirect(skb, cfg->tunnel_ifindex, 0/*egress*/);
}
return 1;
}
#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from sys import argv
from bpf import BPF
from builtins import input
from ctypes import c_int, c_uint
from http.server import HTTPServer, SimpleHTTPRequestHandler
import json
from netaddr import EUI, IPAddress
from pyroute2 import IPRoute, NetNS, IPDB, NSPopen
from socket import htons, AF_INET
from threading import Thread
num_hosts = int(argv[1])
host_id = int(argv[2])
b = BPF(src_file="tunnel_mesh.c")
ingress_fn = b.load_func("handle_ingress", BPF.SCHED_CLS)
egress_fn = b.load_func("handle_egress", BPF.SCHED_CLS)
tunkey2if = b.get_table("tunkey2if")
if2tunkey = b.get_table("if2tunkey")
conf = b.get_table("conf")
ipr = IPRoute()
ipdb = IPDB(nl=ipr)
ifc = ipdb.interfaces.eth0
# ifcs to cleanup at the end
ifc_gc = []
def run():
with ipdb.create(ifname="vxlan0", kind="vxlan", vxlan_id=0,
vxlan_link=ifc, vxlan_port=htons(4789),
vxlan_flowbased=True,
vxlan_collect_metadata=True,
vxlan_learning=False) as vx:
vx.up()
ifc_gc.append(vx.ifname)
conf[c_int(1)] = c_int(vx.index)
ipr.tc("add", "ingress", vx.index, "ffff:")
ipr.tc("add-filter", "bpf", vx.index, ":1", fd=ingress_fn.fd,
name=ingress_fn.name, parent="ffff:", action="drop", classid=1)
for j in range(0, 2):
vni = 10000 + j
with ipdb.create(ifname="br%d" % j, kind="bridge") as br:
for i in range(0, num_hosts):
if i != host_id:
v = ipdb.create(ifname="dummy%d%d" % (j , i), kind="dummy").up().commit()
ipaddr = "172.16.1.%d" % (100 + i)
tunkey2if_key = tunkey2if.Key(vni, IPAddress(ipaddr))
tunkey2if_leaf = tunkey2if.Leaf(v.index)
tunkey2if[tunkey2if_key] = tunkey2if_leaf
if2tunkey_key = if2tunkey.Key(v.index)
if2tunkey_leaf = if2tunkey.Leaf(vni, IPAddress(ipaddr))
if2tunkey[if2tunkey_key] = if2tunkey_leaf
ipr.tc("add", "sfq", v.index, "1:")
ipr.tc("add-filter", "bpf", v.index, ":1", fd=egress_fn.fd,
name=egress_fn.name, parent="1:", action="drop", classid=1)
br.add_port(v)
br.up()
ifc_gc.append(v.ifname)
ifc_gc.append(br.ifname)
try:
run()
input("")
print("---")
finally:
for v in ifc_gc: ipdb.interfaces[v].remove().commit()
ipdb.release()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment