Commit 6d82a586 authored by Brenden Blanco's avatar Brenden Blanco

Make python table accesses more pythonic

* Add [] support in BPF.Table class
* Remove uses of lookup/update
* Add del support
Signed-off-by: default avatarBrenden Blanco <bblanco@plumgrid.com>
parent 41507aee
...@@ -138,11 +138,9 @@ sleep(10) ...@@ -138,11 +138,9 @@ sleep(10)
input("Press enter to exit: ") input("Press enter to exit: ")
stats_collect = {} stats_collect = {}
for key in ingress.iter(): for key, leaf in ingress.items():
leaf = ingress.lookup(key)
stats_collect[key.value] = [leaf.tx_pkts, leaf.tx_bytes, 0, 0] stats_collect[key.value] = [leaf.tx_pkts, leaf.tx_bytes, 0, 0]
for key in egress.iter(): for key, leaf in egress.items():
leaf = egress.lookup(key)
x = stats_collect.get(key.value, [0, 0, 0, 0]) x = stats_collect.get(key.value, [0, 0, 0, 0])
x[2] = leaf.tx_pkts x[2] = leaf.tx_pkts
x[3] = leaf.tx_bytes x[3] = leaf.tx_bytes
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
import atexit import atexit
from collections import MutableMapping
import ctypes as ct import ctypes as ct
import json import json
from past.builtins import basestring from past.builtins import basestring
...@@ -85,14 +86,14 @@ class BPF(object): ...@@ -85,14 +86,14 @@ class BPF(object):
self.name = name self.name = name
self.fd = fd self.fd = fd
class Table(object): class Table(MutableMapping):
def __init__(self, bpf, map_fd, keytype, leaftype): def __init__(self, bpf, map_fd, keytype, leaftype):
self.bpf = bpf self.bpf = bpf
self.map_fd = map_fd self.map_fd = map_fd
self.Key = keytype self.Key = keytype
self.Leaf = leaftype self.Leaf = leaftype
def lookup(self, key): def __getitem__(self, key):
key_p = ct.pointer(key) key_p = ct.pointer(key)
leaf = self.Leaf() leaf = self.Leaf()
leaf_p = ct.pointer(leaf) leaf_p = ct.pointer(leaf)
...@@ -100,18 +101,35 @@ class BPF(object): ...@@ -100,18 +101,35 @@ class BPF(object):
ct.cast(key_p, ct.c_void_p), ct.cast(key_p, ct.c_void_p),
ct.cast(leaf_p, ct.c_void_p)) ct.cast(leaf_p, ct.c_void_p))
if res < 0: if res < 0:
raise Exception("Could not lookup in table") raise KeyError
return leaf return leaf
def update(self, key, leaf, flags=0): def __setitem__(self, key, leaf):
key_p = ct.pointer(key) key_p = ct.pointer(key)
leaf_p = ct.pointer(leaf) leaf_p = ct.pointer(leaf)
res = lib.bpf_update_elem(self.map_fd, res = lib.bpf_update_elem(self.map_fd,
ct.cast(key_p, ct.c_void_p), ct.cast(key_p, ct.c_void_p),
ct.cast(leaf_p, ct.c_void_p), flags) ct.cast(leaf_p, ct.c_void_p), 0)
if res < 0: if res < 0:
raise Exception("Could not update table") raise Exception("Could not update table")
def __len__(self):
i = 0
for k in self: i += 1
return i
def __delitem__(self, key):
key_p = ct.pointer(key)
res = lib.bpf_delete_elem(self.map_fd, ct.cast(key_p, ct.c_void_p))
if res < 0:
raise KeyError
def __iter__(self):
return BPF.Table.Iter(self, self.Key)
def iter(self): return self.__iter__()
def keys(self): return self.__iter__()
class Iter(object): class Iter(object):
def __init__(self, table, keytype): def __init__(self, table, keytype):
self.Key = keytype self.Key = keytype
...@@ -125,9 +143,6 @@ class BPF(object): ...@@ -125,9 +143,6 @@ class BPF(object):
self.key = self.table.next(self.key) self.key = self.table.next(self.key)
return self.key return self.key
def iter(self):
return BPF.Table.Iter(self, self.Key)
def next(self, key): def next(self, key):
next_key = self.Key() next_key = self.Key()
next_key_p = ct.pointer(next_key) next_key_p = ct.pointer(next_key)
......
...@@ -151,14 +151,14 @@ class TestBPFSocket(TestCase): ...@@ -151,14 +151,14 @@ class TestBPFSocket(TestCase):
ip, br_dest_map, br_mac_map, ip, br_dest_map, br_mac_map,
ns_eth_out, vm_mac, vm_ip): ns_eth_out, vm_mac, vm_ip):
val = Bpf_Dest(prog_id_br, curr_br_pid) val = Bpf_Dest(prog_id_br, curr_br_pid)
self.pem_dest.update(c_uint(curr_pem_pid), val) self.pem_dest[c_uint(curr_pem_pid)] = val
val = Bpf_Dest(prog_id_pem, curr_pem_pid) val = Bpf_Dest(prog_id_pem, curr_pem_pid)
br_dest_map.update(c_uint(curr_br_pid), val) br_dest_map[c_uint(curr_br_pid)] = val
ifindex = ip.link_lookup(ifname=ns_eth_out)[0] ifindex = ip.link_lookup(ifname=ns_eth_out)[0]
self.pem_port.update(c_uint(curr_pem_pid), c_uint(ifindex)) self.pem_port[c_uint(curr_pem_pid)] = c_uint(ifindex)
self.pem_ifindex.update(c_uint(ifindex), c_uint(curr_pem_pid)) self.pem_ifindex[c_uint(ifindex)] = c_uint(curr_pem_pid)
mac_addr = Eth_Addr(int(EUI(vm_mac.decode()))) mac_addr = Eth_Addr(int(EUI(vm_mac.decode())))
br_mac_map.update(mac_addr, c_uint(curr_br_pid)) br_mac_map[mac_addr] = c_uint(curr_br_pid)
def attach_filter(self, ip, ifname, fd, name): def attach_filter(self, ip, ifname, fd, name):
ifindex = ip.link_lookup(ifname=ifname)[0] ifindex = ip.link_lookup(ifname=ifname)[0]
...@@ -185,9 +185,9 @@ class TestBPFSocket(TestCase): ...@@ -185,9 +185,9 @@ class TestBPFSocket(TestCase):
self.get_table(b) self.get_table(b)
# configure jump table # configure jump table
self.jump.update(c_uint(prog_id_pem), c_uint(pem_fn.fd)) self.jump[c_uint(prog_id_pem)] = c_uint(pem_fn.fd)
self.jump.update(c_uint(prog_id_br1), c_uint(br1_fn.fd)) self.jump[c_uint(prog_id_br1)] = c_uint(br1_fn.fd)
self.jump.update(c_uint(prog_id_br2), c_uint(br2_fn.fd)) self.jump[c_uint(prog_id_br2)] = c_uint(br2_fn.fd)
# connect pem and br1 # connect pem and br1
curr_pem_pid = curr_pem_pid + 1 curr_pem_pid = curr_pem_pid + 1
...@@ -205,9 +205,9 @@ class TestBPFSocket(TestCase): ...@@ -205,9 +205,9 @@ class TestBPFSocket(TestCase):
# connect <br1, rtr> and <br2, rtr> # connect <br1, rtr> and <br2, rtr>
ifindex = ip.link_lookup(ifname=self.nsrtr_eth0_out)[0] ifindex = ip.link_lookup(ifname=self.nsrtr_eth0_out)[0]
self.br1_rtr.update(c_uint(0), c_uint(ifindex)) self.br1_rtr[c_uint(0)] = c_uint(ifindex)
ifindex = ip.link_lookup(ifname=self.nsrtr_eth1_out)[0] ifindex = ip.link_lookup(ifname=self.nsrtr_eth1_out)[0]
self.br2_rtr.update(c_uint(0), c_uint(ifindex)) self.br2_rtr[c_uint(0)] = c_uint(ifindex)
# tc filter setup with bpf programs attached # tc filter setup with bpf programs attached
self.attach_filter(ip, self.ns1_eth_out, pem_fn.fd, pem_fn.name) self.attach_filter(ip, self.ns1_eth_out, pem_fn.fd, pem_fn.name)
...@@ -246,7 +246,7 @@ class TestBPFSocket(TestCase): ...@@ -246,7 +246,7 @@ class TestBPFSocket(TestCase):
# ping # ping
subprocess.call(["ip", "netns", "exec", self.ns1, "ping", self.vm2_ip, "-c", "2"]) subprocess.call(["ip", "netns", "exec", self.ns1, "ping", self.vm2_ip, "-c", "2"])
# minimum one arp reply, 5 icmp reply # minimum one arp reply, 5 icmp reply
self.assertGreater(self.pem_stats.lookup(c_uint(0)).value, 5) self.assertGreater(self.pem_stats[c_uint(0)].value, 5)
# iperf, run server on the background # iperf, run server on the background
subprocess.Popen(["ip", "netns", "exec", self.ns2, "iperf", "-s", "-xSCD"]) subprocess.Popen(["ip", "netns", "exec", self.ns2, "iperf", "-s", "-xSCD"])
......
...@@ -153,10 +153,10 @@ class TestBPFSocket(TestCase): ...@@ -153,10 +153,10 @@ class TestBPFSocket(TestCase):
ns2_ifindex = ip.link_lookup(ifname=self.ns2_eth_out)[0] ns2_ifindex = ip.link_lookup(ifname=self.ns2_eth_out)[0]
br1_ifindex = ip.link_lookup(ifname=self.veth_br1_2_pem)[0] br1_ifindex = ip.link_lookup(ifname=self.veth_br1_2_pem)[0]
br2_ifindex = ip.link_lookup(ifname=self.veth_br2_2_pem)[0] br2_ifindex = ip.link_lookup(ifname=self.veth_br2_2_pem)[0]
self.pem_dest.update(c_uint(ns1_ifindex), c_uint(br1_ifindex)) self.pem_dest[c_uint(ns1_ifindex)] = c_uint(br1_ifindex)
self.pem_dest.update(c_uint(br1_ifindex), c_uint(ns1_ifindex)) self.pem_dest[c_uint(br1_ifindex)] = c_uint(ns1_ifindex)
self.pem_dest.update(c_uint(ns2_ifindex), c_uint(br2_ifindex)) self.pem_dest[c_uint(ns2_ifindex)] = c_uint(br2_ifindex)
self.pem_dest.update(c_uint(br2_ifindex), c_uint(ns2_ifindex)) self.pem_dest[c_uint(br2_ifindex)] = c_uint(ns2_ifindex)
# tc filter setup with bpf programs attached # tc filter setup with bpf programs attached
self.attach_filter(ip, self.ns1_eth_out, pem_fn.fd, pem_fn.name) self.attach_filter(ip, self.ns1_eth_out, pem_fn.fd, pem_fn.name)
...@@ -190,7 +190,7 @@ class TestBPFSocket(TestCase): ...@@ -190,7 +190,7 @@ class TestBPFSocket(TestCase):
# ping # ping
subprocess.call(["ip", "netns", "exec", self.ns1, "ping", self.vm2_ip, "-c", "2"]) subprocess.call(["ip", "netns", "exec", self.ns1, "ping", self.vm2_ip, "-c", "2"])
# minimum one arp request/reply, 5 icmp request/reply # minimum one arp request/reply, 5 icmp request/reply
self.assertGreater(self.pem_stats.lookup(c_uint(0)).value, 11) self.assertGreater(self.pem_stats[c_uint(0)].value, 11)
# iperf, run server on the background # iperf, run server on the background
subprocess.Popen(["ip", "netns", "exec", self.ns2, "iperf", "-s", "-xSCD"]) subprocess.Popen(["ip", "netns", "exec", self.ns2, "iperf", "-s", "-xSCD"])
......
...@@ -31,18 +31,18 @@ class TestBPFSocket(TestCase): ...@@ -31,18 +31,18 @@ class TestBPFSocket(TestCase):
ip.tc("add-filter", "bpf", ifindex, ":1", fd=ether_fn.fd, ip.tc("add-filter", "bpf", ifindex, ":1", fd=ether_fn.fd,
name=ether_fn.name, parent="1:", action="ok", classid=1) name=ether_fn.name, parent="1:", action="ok", classid=1)
self.jump = b.get_table("jump", c_int, c_int) self.jump = b.get_table("jump", c_int, c_int)
self.jump.update(c_int(S_ARP), c_int(arp_fn.fd)) self.jump[c_int(S_ARP)] = c_int(arp_fn.fd)
self.jump.update(c_int(S_IP), c_int(ip_fn.fd)) self.jump[c_int(S_IP)] = c_int(ip_fn.fd)
self.jump.update(c_int(S_EOP), c_int(eop_fn.fd)) self.jump[c_int(S_EOP)] = c_int(eop_fn.fd)
self.stats = b.get_table("stats", c_int, c_ulonglong) self.stats = b.get_table("stats", c_int, c_ulonglong)
def test_jumps(self): def test_jumps(self):
udp = socket(AF_INET, SOCK_DGRAM) udp = socket(AF_INET, SOCK_DGRAM)
udp.sendto(b"a" * 10, ("172.16.1.1", 5000)) udp.sendto(b"a" * 10, ("172.16.1.1", 5000))
udp.close() udp.close()
self.assertGreater(self.stats.lookup(c_int(S_IP)).value, 0) self.assertGreater(self.stats[c_int(S_IP)].value, 0)
self.assertGreater(self.stats.lookup(c_int(S_ARP)).value, 0) self.assertGreater(self.stats[c_int(S_ARP)].value, 0)
self.assertGreater(self.stats.lookup(c_int(S_EOP)).value, 1) self.assertGreater(self.stats[c_int(S_EOP)].value, 1)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
...@@ -37,14 +37,18 @@ class TestBPFSocket(TestCase): ...@@ -37,14 +37,18 @@ class TestBPFSocket(TestCase):
def test_ping(self): def test_ping(self):
cmd = ["ping", "-f", "-c", "100", "172.16.1.1"] cmd = ["ping", "-f", "-c", "100", "172.16.1.1"]
check_call(cmd) check_call(cmd)
#for key in self.stats.iter(): #for key, leaf in self.stats.items():
# leaf = self.stats.lookup(key)
# print(IPAddress(key.sip), "=>", IPAddress(key.dip), # print(IPAddress(key.sip), "=>", IPAddress(key.dip),
# "rx", leaf.rx_pkts, "tx", leaf.tx_pkts) # "rx", leaf.rx_pkts, "tx", leaf.tx_pkts)
key = self.stats.Key(IPAddress("172.16.1.2").value, IPAddress("172.16.1.1").value) key = self.stats.Key(IPAddress("172.16.1.2").value, IPAddress("172.16.1.1").value)
leaf = self.stats.lookup(key) leaf = self.stats[key]
self.assertEqual(leaf.rx_pkts, 100) self.assertEqual(leaf.rx_pkts, 100)
self.assertEqual(leaf.tx_pkts, 100) self.assertEqual(leaf.tx_pkts, 100)
del self.stats[key]
with self.assertRaises(KeyError):
x = self.stats[key]
with self.assertRaises(KeyError):
del self.stats[key]
if __name__ == "__main__": if __name__ == "__main__":
main() main()
...@@ -41,8 +41,7 @@ class TestKprobe(TestCase): ...@@ -41,8 +41,7 @@ class TestKprobe(TestCase):
with open("/etc/services", "r") as f: with open("/etc/services", "r") as f:
for i in range(0, 200): for i in range(0, 200):
os.read(f.fileno(), 1) os.read(f.fileno(), 1)
for key in self.stats.iter(): for key, leaf in self.stats.items():
leaf = self.stats.lookup(key)
print("fd %x:" % key.fd, "stat1 %d" % leaf.stat1, "stat2 %d" % leaf.stat2) print("fd %x:" % key.fd, "stat1 %d" % leaf.stat1, "stat2 %d" % leaf.stat2)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -32,8 +32,7 @@ class TestTracingEvent(TestCase): ...@@ -32,8 +32,7 @@ class TestTracingEvent(TestCase):
def test_sched1(self): def test_sched1(self):
for i in range(0, 100): for i in range(0, 100):
sleep(0.01) sleep(0.01)
for key in self.stats.iter(): for key, leaf in self.stats.items():
leaf = self.stats.lookup(key)
print("ptr %x:" % key.ptr, "stat1 %x" % leaf.stat1) print("ptr %x:" % key.ptr, "stat1 %x" % leaf.stat1)
if __name__ == "__main__": if __name__ == "__main__":
......
...@@ -32,8 +32,7 @@ class TestBlkRequest(TestCase): ...@@ -32,8 +32,7 @@ class TestBlkRequest(TestCase):
"count=1024", "bs=4096"]) "count=1024", "bs=4096"])
subprocess.call(["sync"]) subprocess.call(["sync"])
os.unlink("/opt/trace3.txt") os.unlink("/opt/trace3.txt")
for key in self.latency.iter(): for key, leaf in self.latency.items():
leaf = self.latency.lookup(key)
print("latency %u:" % key.value, "count %u" % leaf.value) print("latency %u:" % key.value, "count %u" % leaf.value)
sys.stdout.flush() sys.stdout.flush()
......
...@@ -38,15 +38,15 @@ class TestBPFFilter(TestCase): ...@@ -38,15 +38,15 @@ class TestBPFFilter(TestCase):
def test_xlate(self): def test_xlate(self):
key1 = self.xlate.Key(IPAddress("172.16.1.2").value, IPAddress("172.16.1.1").value) key1 = self.xlate.Key(IPAddress("172.16.1.2").value, IPAddress("172.16.1.1").value)
leaf1 = self.xlate.Leaf(IPAddress("192.168.1.2").value, IPAddress("192.168.1.1").value, 0, 0) leaf1 = self.xlate.Leaf(IPAddress("192.168.1.2").value, IPAddress("192.168.1.1").value, 0, 0)
self.xlate.update(key1, leaf1) self.xlate[key1] = leaf1
key2 = self.xlate.Key(IPAddress("192.168.1.1").value, IPAddress("192.168.1.2").value) key2 = self.xlate.Key(IPAddress("192.168.1.1").value, IPAddress("192.168.1.2").value)
leaf2 = self.xlate.Leaf(IPAddress("172.16.1.1").value, IPAddress("172.16.1.2").value, 0, 0) leaf2 = self.xlate.Leaf(IPAddress("172.16.1.1").value, IPAddress("172.16.1.2").value, 0, 0)
self.xlate.update(key2, leaf2) self.xlate[key2] = leaf2
call(["ping", "-c1", "192.168.1.1"]) call(["ping", "-c1", "192.168.1.1"])
leaf = self.xlate.lookup(key1) leaf = self.xlate[key1]
self.assertGreater(leaf.ip_xlated_pkts, 0) self.assertGreater(leaf.ip_xlated_pkts, 0)
self.assertGreater(leaf.arp_xlated_pkts, 0) self.assertGreater(leaf.arp_xlated_pkts, 0)
leaf = self.xlate.lookup(key2) leaf = self.xlate[key2]
self.assertGreater(leaf.ip_xlated_pkts, 0) self.assertGreater(leaf.ip_xlated_pkts, 0)
self.assertGreater(leaf.arp_xlated_pkts, 0) self.assertGreater(leaf.arp_xlated_pkts, 0)
......
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