diff options
author | Neale Ranns <neale.ranns@cisco.com> | 2018-02-05 01:13:38 -0800 |
---|---|---|
committer | Damjan Marion <dmarion.lists@gmail.com> | 2018-02-09 13:17:54 +0000 |
commit | bc27d1be24815e1371dcce3bff2d3075a532acba (patch) | |
tree | c17db02fefb19ce593de5ddb2444f4c97e074492 /test | |
parent | ef56fae51a8683ec6ceeb01e1374cde2ba30c1e5 (diff) |
GBP plugin
Group Base Policy (GBP) defines:
- endpoints: typically a VM or container that is connected to the
virtual switch/router (i.e. to VPP)
- endpoint-group: (EPG) a collection of endpoints
- policy: rules determining which traffic can pass between EPGs a.k.a
a 'contract'
Here, policy is implemented via an ACL.
EPG classification for transit packets is determined by:
- source EPG: from the packet's input interface
- destination EPG: from the packet's destination IP address.
Change-Id: I7b983844826b5fc3d49e21353ebda9df9b224e25
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/test_gbp.py | 369 | ||||
-rw-r--r-- | test/vpp_papi_provider.py | 27 |
2 files changed, 396 insertions, 0 deletions
diff --git a/test/test_gbp.py b/test/test_gbp.py new file mode 100644 index 00000000000..427b14de506 --- /dev/null +++ b/test/test_gbp.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python + +import unittest +import socket +import struct + +from framework import VppTestCase, VppTestRunner +from vpp_object import VppObject + +from scapy.packet import Raw +from scapy.layers.l2 import Ether +from scapy.layers.inet import IP, UDP +from scapy.layers.inet6 import IPv6 + +from socket import AF_INET, AF_INET6 +from scapy.utils import inet_pton + + +class VppGbpEndpoint(VppObject): + """ + GDB Endpoint + """ + + def __init__(self, test, sw_if_index, addr, epg, is_ip6=0): + self._test = test + self.sw_if_index = sw_if_index + self.epg = epg + self.addr_p = addr + self.is_ip6 = is_ip6 + if is_ip6: + self.addr = inet_pton(AF_INET6, addr) + else: + self.addr = inet_pton(AF_INET, addr) + + def add_vpp_config(self): + self._test.vapi.gbp_endpoint_add_del( + 1, + self.sw_if_index, + self.addr, + self.is_ip6, + self.epg) + self._test.registry.register(self, self._test.logger) + + def remove_vpp_config(self): + self._test.vapi.gbp_endpoint_add_del( + 0, + self.sw_if_index, + self.addr, + self.is_ip6, + self.epg) + + def __str__(self): + return self.object_id() + + def object_id(self): + return "gbp-endpoint;[%d:%s:%d]" % (self.sw_if_index, + self.addr_p, + self.epg) + + def query_vpp_config(self): + eps = self._test.vapi.gbp_endpoint_dump() + for ep in eps: + if ep.endpoint.address == self.addr \ + and ep.endpoint.sw_if_index == self.sw_if_index: + return True + return False + + +class VppGbpContract(VppObject): + """ + GDB Contract + """ + + def __init__(self, test, src_epg, dst_epg, acl_index): + self._test = test + self.acl_index = acl_index + self.src_epg = src_epg + self.dst_epg = dst_epg + + def add_vpp_config(self): + self._test.vapi.gbp_contract_add_del( + 1, + self.src_epg, + self.dst_epg, + self.acl_index) + self._test.registry.register(self, self._test.logger) + + def remove_vpp_config(self): + self._test.vapi.gbp_contract_add_del( + 0, + self.src_epg, + self.dst_epg, + self.acl_index) + + def __str__(self): + return self.object_id() + + def object_id(self): + return "gbp-contract;[%d:%s:%d]" % (self.src_epg, + self.dst_epg, + self.acl_index) + + def query_vpp_config(self): + eps = self._test.vapi.gbp_contract_dump() + for ep in eps: + if ep.contract.src_epg == self.src_epg \ + and ep.contract.dst_epg == self.dst_epg: + return True + return False + + +class TestGBP(VppTestCase): + """ GBP Test Case """ + + def setUp(self): + super(TestGBP, self).setUp() + + # create 6 pg interfaces for pg0 to pg5 + self.create_pg_interfaces(range(6)) + + for i in self.pg_interfaces: + i.admin_up() + i.config_ip4() + i.resolve_arp() + i.config_ip6() + i.resolve_ndp() + + def tearDown(self): + for i in self.pg_interfaces: + i.unconfig_ip4() + i.unconfig_ip6() + + super(TestGBP, self).tearDown() + + def test_gbp4(self): + """ Group Based Policy v4 """ + + ep1 = VppGbpEndpoint(self, + self.pg0.sw_if_index, + self.pg0.remote_ip4, + 220) + ep1.add_vpp_config() + ep2 = VppGbpEndpoint(self, + self.pg1.sw_if_index, + self.pg1.remote_ip4, + 220) + ep2.add_vpp_config() + + ep3 = VppGbpEndpoint(self, + self.pg2.sw_if_index, + self.pg2.remote_ip4, + 221) + ep3.add_vpp_config() + ep4 = VppGbpEndpoint(self, + self.pg3.sw_if_index, + self.pg3.remote_ip4, + 222) + ep4.add_vpp_config() + + self.logger.info(self.vapi.cli("sh gbp endpoint")) + + # + # in the abscense of policy, endpoints in the same EPG + # can communicate + # + pkt_intra_epg = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg1.remote_ip4) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1) + + # + # in the abscense of policy, endpoints in the different EPG + # cannot communicate + # + pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg2.remote_ip4) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg3.remote_ip4) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IP(src=self.pg2.remote_ip4, + dst=self.pg0.remote_ip4) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_221 * 65) + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_221_to_220 * 65) + + # + # A uni-directional contract from EPG 220 -> 221 + # + c1 = VppGbpContract(self, 220, 221, 0xffffffff) + c1.add_vpp_config() + + self.send_and_expect(self.pg0, + pkt_inter_epg_220_to_221 * 65, + self.pg2) + self.send_and_assert_no_replies(self.pg2, + pkt_inter_epg_221_to_220 * 65) + + # + # contract for the return direction + # + c2 = VppGbpContract(self, 221, 220, 0xffffffff) + c2.add_vpp_config() + + self.send_and_expect(self.pg0, + pkt_inter_epg_220_to_221 * 65, + self.pg2) + self.send_and_expect(self.pg2, + pkt_inter_epg_221_to_220 * 65, + self.pg0) + + # + # check that inter group is still disabled for the groups + # not in the contract. + # + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_222 * 65) + + self.logger.info(self.vapi.cli("sh gbp contract")) + + # + # remove both contracts, traffic stops in both directions + # + c2.remove_vpp_config() + c1.remove_vpp_config() + + self.send_and_assert_no_replies(self.pg2, + pkt_inter_epg_221_to_220 * 65) + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_221 * 65) + self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1) + + def test_gbp6(self): + """ Group Based Policy v6 """ + + ep1 = VppGbpEndpoint(self, + self.pg0.sw_if_index, + self.pg0.remote_ip6, + 220, + is_ip6=1) + ep1.add_vpp_config() + ep2 = VppGbpEndpoint(self, + self.pg1.sw_if_index, + self.pg1.remote_ip6, + 220, + is_ip6=1) + ep2.add_vpp_config() + + ep3 = VppGbpEndpoint(self, + self.pg2.sw_if_index, + self.pg2.remote_ip6, + 221, + is_ip6=1) + ep3.add_vpp_config() + ep4 = VppGbpEndpoint(self, + self.pg3.sw_if_index, + self.pg3.remote_ip6, + 222, + is_ip6=1) + ep4.add_vpp_config() + + self.logger.info(self.vapi.cli("sh gbp endpoint")) + + # + # in the abscense of policy, endpoints in the same EPG + # can communicate + # + pkt_intra_epg = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IPv6(src=self.pg0.remote_ip6, + dst=self.pg1.remote_ip6) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1) + + # + # in the abscense of policy, endpoints in the different EPG + # cannot communicate + # + pkt_inter_epg_220_to_221 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IPv6(src=self.pg0.remote_ip6, + dst=self.pg2.remote_ip6) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + pkt_inter_epg_220_to_222 = (Ether(src=self.pg0.remote_mac, + dst=self.pg0.local_mac) / + IPv6(src=self.pg0.remote_ip6, + dst=self.pg3.remote_ip6) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + pkt_inter_epg_221_to_220 = (Ether(src=self.pg2.remote_mac, + dst=self.pg2.local_mac) / + IPv6(src=self.pg2.remote_ip6, + dst=self.pg0.remote_ip6) / + UDP(sport=1234, dport=1234) / + Raw('\xa5' * 100)) + + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_221 * 65) + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_221_to_220 * 65) + + # + # A uni-directional contract from EPG 220 -> 221 + # + c1 = VppGbpContract(self, 220, 221, 0xffffffff) + c1.add_vpp_config() + + self.send_and_expect(self.pg0, + pkt_inter_epg_220_to_221 * 65, + self.pg2) + self.send_and_assert_no_replies(self.pg2, + pkt_inter_epg_221_to_220 * 65) + + # + # contract for the return direction + # + c2 = VppGbpContract(self, 221, 220, 0xffffffff) + c2.add_vpp_config() + + self.send_and_expect(self.pg0, + pkt_inter_epg_220_to_221 * 65, + self.pg2) + self.send_and_expect(self.pg2, + pkt_inter_epg_221_to_220 * 65, + self.pg0) + + # + # check that inter group is still disabled for the groups + # not in the contract. + # + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_222 * 65) + + self.logger.info(self.vapi.cli("sh gbp contract")) + + # + # remove both contracts, traffic stops in both directions + # + c2.remove_vpp_config() + c1.remove_vpp_config() + + self.send_and_assert_no_replies(self.pg2, + pkt_inter_epg_221_to_220 * 65) + self.send_and_assert_no_replies(self.pg0, + pkt_inter_epg_220_to_221 * 65) + self.send_and_expect(self.pg0, pkt_intra_epg * 65, self.pg1) + + +if __name__ == '__main__': + unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index a10b777a13a..15a566c5bc7 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -3162,3 +3162,30 @@ class VppPapiProvider(object): def ip_reassembly_get(self, is_ip6=0): """ Get IP reassembly parameters """ return self.api(self.papi.ip_reassembly_get, {'is_ip6': is_ip6}) + + def gbp_endpoint_add_del(self, is_add, sw_if_index, addr, is_ip6, epg): + """ GBP endpoint Add/Del """ + return self.api(self.papi.gbp_endpoint_add_del, + {'is_add': is_add, + 'endpoint': { + 'is_ip6': is_ip6, + 'sw_if_index': sw_if_index, + 'address': addr, + 'epg_id': epg}}) + + def gbp_endpoint_dump(self): + """ GBP endpoint Dump """ + return self.api(self.papi.gbp_endpoint_dump, {}) + + def gbp_contract_add_del(self, is_add, src_epg, dst_epg, acl_index): + """ GBP contract Add/Del """ + return self.api(self.papi.gbp_contract_add_del, + {'is_add': is_add, + 'contract': { + 'acl_index': acl_index, + 'src_epg': src_epg, + 'dst_epg': dst_epg}}) + + def gbp_contract_dump(self): + """ GBP contract Dump """ + return self.api(self.papi.gbp_contract_dump, {}) |