Commit 8a9747c9 authored by Brenden Blanco's avatar Brenden Blanco

Merge pull request #90 from iovisor/yhs_dev

simply vlan_learning example with newer vlan_push/pop helpers
parents c366fcf2 6d8381c7
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
struct ifindex_leaf_t { struct ifindex_leaf_t {
int out_ifindex; int out_ifindex;
int vlan_tci; // populated by phys2virt and used by virt2phys
int vlan_proto; // populated by phys2virt and used by virt2phys
u64 tx_pkts; u64 tx_pkts;
u64 tx_bytes; u64 tx_bytes;
}; };
...@@ -16,6 +18,9 @@ BPF_TABLE("hash", int, struct ifindex_leaf_t, egress, 4096); ...@@ -16,6 +18,9 @@ BPF_TABLE("hash", int, struct ifindex_leaf_t, egress, 4096);
BPF_TABLE("hash", u64, struct ifindex_leaf_t, ingress, 4096); BPF_TABLE("hash", u64, struct ifindex_leaf_t, ingress, 4096);
int handle_phys2virt(struct __sk_buff *skb) { int handle_phys2virt(struct __sk_buff *skb) {
// only handle vlan packets
if (!skb->vlan_present)
return 1;
u8 *cursor = 0; u8 *cursor = 0;
ethernet: { ethernet: {
struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet)); struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
...@@ -28,9 +33,12 @@ int handle_phys2virt(struct __sk_buff *skb) { ...@@ -28,9 +33,12 @@ int handle_phys2virt(struct __sk_buff *skb) {
int out_ifindex = leaf->out_ifindex; int out_ifindex = leaf->out_ifindex;
struct ifindex_leaf_t zleaf = {0}; struct ifindex_leaf_t zleaf = {0};
struct ifindex_leaf_t *out_leaf = egress.lookup_or_init(&out_ifindex, &zleaf); struct ifindex_leaf_t *out_leaf = egress.lookup_or_init(&out_ifindex, &zleaf);
// relearn when mac moves ifindex // to capture potential configuration changes
if (out_leaf->out_ifindex != skb->ifindex) out_leaf->out_ifindex = skb->ifindex;
out_leaf->out_ifindex = skb->ifindex; out_leaf->vlan_tci = skb->vlan_tci;
out_leaf->vlan_proto = skb->vlan_proto;
// pop the vlan header and send to the destination
bpf_skb_vlan_pop(skb);
bpf_clone_redirect(skb, leaf->out_ifindex, 0); bpf_clone_redirect(skb, leaf->out_ifindex, 0);
} }
} }
...@@ -46,6 +54,7 @@ int handle_virt2phys(struct __sk_buff *skb) { ...@@ -46,6 +54,7 @@ int handle_virt2phys(struct __sk_buff *skb) {
if (leaf) { if (leaf) {
lock_xadd(&leaf->tx_pkts, 1); lock_xadd(&leaf->tx_pkts, 1);
lock_xadd(&leaf->tx_bytes, skb->len); lock_xadd(&leaf->tx_bytes, skb->len);
bpf_skb_vlan_push(skb, leaf->vlan_proto, leaf->vlan_tci);
bpf_clone_redirect(skb, leaf->out_ifindex, 0); bpf_clone_redirect(skb, leaf->out_ifindex, 0);
} }
} }
......
...@@ -14,14 +14,14 @@ ...@@ -14,14 +14,14 @@
# overlapping IP spaces and the traffic will still work. # overlapping IP spaces and the traffic will still work.
# | bpf program | # | bpf program |
# cli0 --| | |----\ /--|-- worker0 | # cli0 --| | /--|-- worker0 |
# cli1 --| trunk | |----->-handle_p2v(pkt)-> /---|-- worker1 | # cli1 --| trunk | +->--->-handle_p2v(pkt)-> /---|-- worker1 |
# cli2 --|=======|=|----/ /----|-- worker2 | # cli2 --|=======|=+ /----|-- worker2 |
# ... --| | |---/ <-handle_v2p(pkt)-<-----|-- ... | # ... --| | +-<---<-handle_v2p(pkt)-<-----|-- ... |
# cliN --| | |--/ \----|-- workerM | # cliN --| | \----|-- workerM |
# | | ^ ^ | # | | ^ |
# phys | vlan veth | # phys | veth |
# switch | subinterface | # switch | |
from bpf import BPF from bpf import BPF
from builtins import input from builtins import input
...@@ -63,22 +63,12 @@ class VlanSimulation(Simulation): ...@@ -63,22 +63,12 @@ class VlanSimulation(Simulation):
v.up() v.up()
self.ipdb.interfaces.eth0b.up().commit() self.ipdb.interfaces.eth0b.up().commit()
# connect the trunk to the bridge # eth0a will be hooked to clients with vlan interfaces
with self.ipdb.create(ifname="br100", kind="bridge") as br100: # add the bpf program to eth0b for demuxing phys2virt packets
br100.add_port(self.ipdb.interfaces.eth0b) v = self.ipdb.interfaces["eth0b"]
br100.up() ipr.tc("add", "ingress", v["index"], "ffff:")
ipr.tc("add-filter", "bpf", v["index"], ":1", fd=phys_fn.fd,
# for each vlan, create a subinterface on the eth...most of these will be name=phys_fn.name, parent="ffff:", action="drop", classid=1)
# unused, but still listening and waiting for a client to send traffic on
for i in range(2, 2 + num_vlans):
with self.ipdb.create(ifname="eth0a.%d" % i, kind="vlan",
link=ipdb.interfaces.eth0a, vlan_id=i) as v:
v.up()
v = self.ipdb.interfaces["eth0a.%d" % i]
# add the bpf program for demuxing phys2virt packets
ipr.tc("add", "ingress", v["index"], "ffff:")
ipr.tc("add-filter", "bpf", v["index"], ":1", fd=phys_fn.fd,
name=phys_fn.name, parent="ffff:", action="drop", classid=1)
# allocate vlans randomly # allocate vlans randomly
available_vlans = [i for i in range(2, 2 + num_vlans)] available_vlans = [i for i in range(2, 2 + num_vlans)]
...@@ -93,15 +83,15 @@ class VlanSimulation(Simulation): ...@@ -93,15 +83,15 @@ class VlanSimulation(Simulation):
# assign this client to the given worker # assign this client to the given worker
idx = self.ipdb.interfaces["worker%da" % i]["index"] idx = self.ipdb.interfaces["worker%da" % i]["index"]
mac = int(macaddr.replace(":", ""), 16) mac = int(macaddr.replace(":", ""), 16)
ingress[ingress.Key(mac)] = ingress.Leaf(idx, 0, 0) ingress[ingress.Key(mac)] = ingress.Leaf(idx, 0, 0, 0, 0)
# test traffic with curl loop # test traffic with curl loop
cmd = ["bash", "-c", cmd = ["bash", "-c",
"for i in {1..8}; do curl 172.16.1.5 -o /dev/null; sleep 1; done"] "for i in {1..8}; do curl 172.16.1.5 -o /dev/null; sleep 1; done"]
br_ifc = self.ipdb.create(ifname="br100.%d" % i, kind="vlan", client_ifc = self.ipdb.create(ifname="eth0a.%d" % i, kind="vlan",
link=br100, link=self.ipdb.interfaces["eth0a"],
vlan_id=available_vlans.pop(0)).commit() vlan_id=available_vlans.pop(0)).commit()
(out_ifc, in_ifc) = self._create_ns("client%d" % i, in_ifc=br_ifc, (out_ifc, in_ifc) = self._create_ns("client%d" % i, in_ifc=client_ifc,
ipaddr="172.16.1.100/24", ipaddr="172.16.1.100/24",
macaddr=macaddr, cmd=cmd)[1:3] macaddr=macaddr, cmd=cmd)[1:3]
...@@ -123,6 +113,5 @@ try: ...@@ -123,6 +113,5 @@ try:
print(" tx pkts = %u, tx bytes = %u" % (v[2], v[3])) print(" tx pkts = %u, tx bytes = %u" % (v[2], v[3]))
finally: finally:
if "eth0a" in ipdb.interfaces: ipdb.interfaces.eth0a.remove().commit() if "eth0a" in ipdb.interfaces: ipdb.interfaces.eth0a.remove().commit()
if "br100" in ipdb.interfaces: ipdb.interfaces.br100.remove().commit()
if "sim" in locals(): sim.release() if "sim" in locals(): sim.release()
ipdb.release() ipdb.release()
...@@ -249,6 +249,15 @@ enum bpf_func_id { ...@@ -249,6 +249,15 @@ enum bpf_func_id {
* Return: 0 on success * Return: 0 on success
*/ */
BPF_FUNC_get_current_comm, BPF_FUNC_get_current_comm,
/**
* bpf_get_cgroup_classid(skb) - retrieve a proc's classid
* @skb: pointer to skb
* Return: classid if != 0
*/
BPF_FUNC_get_cgroup_classid,
BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */
__BPF_FUNC_MAX_ID, __BPF_FUNC_MAX_ID,
}; };
......
...@@ -74,6 +74,12 @@ static u64 (*bpf_get_current_uid_gid)(void) = ...@@ -74,6 +74,12 @@ static u64 (*bpf_get_current_uid_gid)(void) =
(void *) BPF_FUNC_get_current_uid_gid; (void *) BPF_FUNC_get_current_uid_gid;
static int (*bpf_get_current_comm)(void *buf, int buf_size) = static int (*bpf_get_current_comm)(void *buf, int buf_size) =
(void *) BPF_FUNC_get_current_comm; (void *) BPF_FUNC_get_current_comm;
static u64 (*bpf_get_cgroup_classid)(void *ctx) =
(void *) BPF_FUNC_get_cgroup_classid;
static u64 (*bpf_skb_vlan_push)(void *ctx, u16 proto, u16 vlan_tci) =
(void *) BPF_FUNC_skb_vlan_push;
static u64 (*bpf_skb_vlan_pop)(void *ctx) =
(void *) BPF_FUNC_skb_vlan_pop;
static void bpf_tail_call_(u64 map_fd, void *ctx, int index) { static void bpf_tail_call_(u64 map_fd, void *ctx, int index) {
((void (*)(void *, u64, int))BPF_FUNC_tail_call)(ctx, map_fd, index); ((void (*)(void *, u64, int))BPF_FUNC_tail_call)(ctx, map_fd, index);
} }
......
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