#!/usr/bin/env python """ACL plugin - MACIP tests """ import random import re import unittest from socket import inet_ntop, inet_pton, AF_INET, AF_INET6 from struct import * from scapy.packet import Raw from scapy.layers.l2 import Ether from scapy.layers.inet import IP, UDP, TCP from scapy.layers.inet6 import IPv6 from framework import VppTestCase, VppTestRunner, running_extended_tests from vpp_lo_interface import VppLoInterface class TestMACIP(VppTestCase): """MACIP Test Case""" DEBUG = False BRIDGED = True ROUTED = False IS_IP4 = False IS_IP6 = True # rule types DENY = 0 PERMIT = 1 # ACL types EXACT_IP = 1 SUBNET_IP = 2 WILD_IP = 3 EXACT_MAC = 1 WILD_MAC = 2 OUI_MAC = 3 ACLS = [] @classmethod def setUpClass(cls): """ Perform standard class setup (defined by class method setUpClass in class VppTestCase) before running the test case, set test case related variables and configure VPP. """ super(TestMACIP, cls).setUpClass() cls.pg_if_packet_sizes = [64, 512, 1518, 9018] # packet sizes cls.bd_id = 10 cls.remote_hosts_count = 250 try: # create 3 pg interfaces, 1 loopback interface cls.create_pg_interfaces(range(3)) cls.create_loopback_interfaces(range(1)) cls.interfaces = list(cls.pg_interfaces) cls.interfaces.extend(cls.lo_interfaces) for i in cls.interfaces: i.admin_up() # Create BD with MAC learning enabled and put interfaces to this BD cls.vapi.sw_interface_set_l2_bridge( cls.loop0.sw_if_index, bd_id=cls.bd_id, bvi=1) cls.vapi.sw_interface_set_l2_bridge( cls.pg0.sw_if_index, bd_id=cls.bd_id) cls.vapi.sw_interface_set_l2_bridge( cls.pg1.sw_if_index, bd_id=cls.bd_id) # Configure IPv4 addresses on loop interface and routed interface cls.loop0.config_ip4() cls.loop0.config_ip6() cls.pg2.config_ip4() cls.pg2.config_ip6() # Configure MAC address binding to IPv4 neighbors on loop0 cls.loop0.generate_remote_hosts(cls.remote_hosts_count) # Modify host mac addresses to have different OUI parts for i in range(2, cls.remote_hosts_count + 2): mac = cls.loop0.remote_hosts[i-2]._mac.split(':') mac[2] = format(int(mac[2], 16) + i, "02x") cls.loop0.remote_hosts[i - 2]._mac = ":".join(mac) cls.loop0.configure_ipv4_neighbors() cls.loop0.configure_ipv6_neighbors() # configure MAC address on pg2 cls.pg2.resolve_arp() cls.pg2.resolve_ndp() # Loopback BVI interface has remote hosts # one half of hosts are behind pg0 second behind pg1 half = cls.remote_hosts_count // 2 cls.pg0.remote_hosts = cls.loop0.remote_hosts[:half] cls.pg1.remote_hosts = cls.loop0.remote_hosts[half:] except Exception: super(TestMACIP, cls).tearDownClass() raise def setUp(self): super(TestMACIP, self).setUp() self.reset_packet_infos() del self.ACLS[:] def tearDown(self): """ Show various debug prints after each test. """ super(TestMACIP, self).tearDown() if not self.vpp_dead: self.logger.info(self.vapi.ppcli("show interface address")) self.logger.info(self.vapi.ppcli("show hardware")) self.logger.info(self.vapi.ppcli("sh acl-plugin macip acl")) self.logger.info(self.vapi.ppcli("sh acl-plugin macip interface")) self.logger.info(self.vapi.ppcli("sh classify tables verbose")) # print self.vapi.ppcli("show interface address") # print self.vapi.ppcli("show hardware") # print self.vapi.ppcli("sh acl-plugin macip interface") # print self.vapi.ppcli("sh acl-plugin macip acl") self.delete_acls() def macip_acl_dump_debug(self): acls = self.vapi.macip_acl_dump() if self.DEBUG: for acl in acls: print "ACL #"+str(acl.acl_index) for r in acl.r: rule = "ACTION" if r.is_permit == 1: rule = "PERMIT" elif r.is_permit == 0: rule = "DENY " print " IP6" if r.is_ipv6 else " IP4", \ rule, \ r.src_mac.encode('hex'), \ r.src_mac_mask.encode('hex'),\ unpack('<16B', r.src_ip_addr), \ r.src_ip_prefix_len return acls def create_rules(self, mac_type=EXACT_MAC, ip_type=EXACT_IP, acl_count=1, rules_count=[1]): acls = [] src_mac = int("220000dead00", 16) for acl in range(2, (acl_count+1) * 2): rules = [] host = random.choice(self.loop0.remote_hosts) is_ip6 = acl % 2 ip4 = host.ip4.split('.') ip6 = list(unpack('<16B', inet_pton(AF_INET6, host.ip6))) if ip_type == self.EXACT_IP: prefix_len4 = 32 prefix_len6 = 128 elif ip_type == self.WILD_IP: ip4 = [0, 0, 0, 0] ip6 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] prefix_len4 = 0 prefix_len6 = 0 rules_count[(acl / 2) - 1] = 1 else: prefix_len4 = 24 prefix_len6 = 64 if mac_type == self.EXACT_MAC: mask = "ff:ff:ff:ff:ff:ff" elif mac_type == self.WILD_MAC: mask = "00:00:00:00:00:00" elif mac_type == self.OUI_MAC: mask = "ff:ff:ff:00:00:00" else: mask = "ff:ff:ff:ff:ff:00" ip = ip6 if is_ip6 else ip4 ip_len = prefix_len6 if is_ip6 else prefix_len4 for i in range(0, rules_count[(acl / 2) - 1]): src_mac += 16777217 if mac_type == self.WILD_MAC: mac = "00:00:00:00:00:00" elif mac_type == self.OUI_MAC: mac = ':'.join(re.findall('..', '{:02x}'.format( src_mac))[:3])+":00:00:00" else: mac = ':'.join(re.findall('..', '{:02x}'.format(src_mac))) if ip_type == self.EXACT_IP: ip4[3] = random.randint(100, 200) ip6[15] = random.randint(100, 200) elif ip_type == self.SUBNET_IP: ip4[2] = random.randint(100, 200) ip4[3] = 0 ip6[8] = random.randint(100, 200) ip6[15] = 0 ip_pack = '' for j in range(0, len(ip)): ip_pack += pack(' 0: continue if is_permit: rule = ({'is_permit': is_permit, 'is_ipv6': is_ip6, 'src_ip_addr': ip_rule, 'src_ip_prefix_len': prefix_len, 'src_mac': mac_rule.replace(':', '').decode('hex'), 'src_mac_mask': mac_mask.replace(':', '').decode( 'hex')}) rules.append(rule) # deny all other packets if not (mac_type == self.WILD_MAC and ip_type == self.WILD_IP): rule = ({'is_permit': 0, 'is_ipv6': is_ip6, 'src_ip_addr': "", 'src_ip_prefix_len': 0, 'src_mac': "", 'src_mac_mask': ""}) rules.append(rule) return {'stream': packets, 'rules': rules} def verify_capture(self, stream, capture, is_ip6): p_l3 = IPv6 if is_ip6 else IP if self.DEBUG: for p in stream: print p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst acls = self.macip_acl_dump_debug() # TODO : verify # for acl in acls: # for r in acl.r: # print r.src_mac.encode('hex'), \ # r.src_mac_mask.encode('hex'),\ # unpack('<16B', r.src_ip_addr), \ # r.src_ip_prefix_len # # for p in capture: # print p[Ether].src, p[Ether].dst, p[p_l3].src, p[p_l3].dst # data = p[Raw].load.split(':',1)[1] # print p[p_l3].src, data def run_traffic(self, mac_type, ip_type, bridged_routed, is_ip6, packets, do_not_expected_capture=False): self.reset_packet_infos() tx_if = self.pg0 if bridged_routed == self.BRIDGED else self.pg2 rx_if = self.pg2 if bridged_routed == self.BRIDGED else self.pg0 test_dict = self.create_stream(mac_type, ip_type, packets, self.pg2, self.loop0, bridged_routed, is_ip6) reply = self.vapi.macip_acl_add(test_dict['rules']) self.assertEqual(reply.retval, 0) acl_index = reply.acl_index self.vapi.macip_acl_interface_add_del(sw_if_index=tx_if.sw_if_index, acl_index=acl_index) reply = self.vapi.macip_acl_interface_get() self.assertEqual(reply.acls[tx_if.sw_if_index], acl_index) self.ACLS.append(reply.acls[tx_if.sw_if_index]) tx_if.add_stream(test_dict['stream']) self.pg_enable_capture(self.pg_interfaces) self.pg_start() if do_not_expected_capture: rx_if.get_capture(0) else: packet_count = self.get_packet_count_for_if_idx( self.loop0.sw_if_index) if mac_type == self.WILD_MAC and ip_type == self.WILD_IP: packet_count = packets if bridged_routed else packet_count capture = rx_if.get_capture(packet_count) self.verify_capture(test_dict['stream'], capture, is_ip6) def run_test_acls(self, mac_type, ip_type, acl_count, rules_count, traffic=None, ip=None): self.apply_rules(self.create_rules(mac_type, ip_type, acl_count, rules_count)) self.verify_acls(acl_count, rules_count) if traffic is not None: self.run_traffic(self.EXACT_MAC, self.EXACT_IP, traffic, ip, 9) def test_acl_bridged_ip4_exactMAC_exactIP(self): """ IP4 MACIP exactMAC|exactIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED, self.IS_IP4, 9) def test_acl_bridged_ip6_exactMAC_exactIP(self): """ IP6 MACIP exactMAC|exactIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.EXACT_IP, self.BRIDGED, self.IS_IP6, 9) def test_acl_bridged_ip4_exactMAC_subnetIP(self): """ IP4 MACIP exactMAC|subnetIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.SUBNET_IP, self.BRIDGED, self.IS_IP4, 9) def test_acl_bridged_ip6_exactMAC_subnetIP(self): """ IP6 MACIP exactMAC|subnetIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.SUBNET_IP, self.BRIDGED, self.IS_IP6, 9) def test_acl_bridged_ip4_exactMAC_wildIP(self): """ IP4 MACIP exactMAC|wildIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.WILD_IP, self.BRIDGED, self.IS_IP4, 9) def test_acl_bridged_ip6_exactMAC_wildIP(self): """ IP6 MACIP exactMAC|wildIP ACL bridged traffic """ self.run_traffic(self.EXACT_MAC, self.WILD_IP, self.BRIDGED, self.IS_IP6, 9) def test_acl_bridged_ip4_ouiMAC_exactIP(self): """ IP4 MACIP ouiMAC|exactIP ACL bridged traffic """ self.run_traffic(self.OUI_MAC, self.EXACT_IP, self.BRIDGED, self.IS_IP4, 3) def test_acl_bridged_ip6_ouiMAC_exactIP(self): """ IP6 MACIP oui_MAC|e
/*
  Copyright (c) 2014 Cisco and/or its affiliates.

  * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

/** @cond DOCUMENTATION_IS_IN_BIHASH_DOC_H */

/*
 * Note: to instantiate the template multiple times in a single file,
 * #undef __included_bihash_template_h__...
 */
#ifndef __included_bihash_template_h__
#define __included_bihash_template_h__

#include <vppinfra/heap.h>
#include <vppinfra/format.h>
#include <vppinfra/pool.h>
#include <vppinfra/cache.h>
#include <vppinfra/lock.h>

#ifndef BIHASH_TYPE
#error BIHASH_TYPE not defined
#endif

#ifdef BIHASH_32_64_SVM
#undef HAVE_MEMFD_CREATE
#include <vppinfra/linux/syscall.h>
#include <fcntl.h>
#define F_LINUX_SPECIFIC_BASE 1024
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
#define F_SEAL_SHRINK (2)
/* Max page size 2**16 due to refcount width  */
#define BIHASH_FREELIST_LENGTH 17
#endif

#define _bv(a,b) a##b
#define __bv(a,b) _bv(a,b)
#define BV(a) __bv(a,BIHASH_TYPE)

#define _bvt(a,b) a##b##_t
#define __bvt(a,b) _bvt(a,b)
#define BVT(a) __bvt(a,BIHASH_TYPE)

#define _bvs(a,b) struct a##b
#define __bvs(a,b) _bvs(a,b)
#define BVS(a) __bvs(a,BIHASH_TYPE)

#if _LP64 == 0
#define OVERFLOW_ASSERT(x) ASSERT(((x) & 0xFFFFFFFF00000000ULL) == 0)
#define u64_to_pointer(x) (void *)(u32)((x))
#define pointer_to_u64(x) (u64)(u32)((x))
#else
#define OVERFLOW_ASSERT(x)
#define u64_to_pointer(x) (void *)((x))
#define pointer_to_u64(x) (u64)((x))
#endif

typedef struct BV (clib_bihash_value)
{
  union
  {
    BVT (clib_bihash_kv) kvp[BIHASH_KVP_PER_PAGE];
    u64 next_free_as_u64;
  };
} BVT (clib_bihash_value);

#define BIHASH_BUCKET_OFFSET_BITS 36

typedef struct
{
  union
  {