aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_vxlan.py
blob: 1978cf0c0184d7e2200f7cfcbf8f6fd00d528517 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/env python

import unittest
from framework import VppTestCase, VppTestRunner
from template_bd import BridgeDomain

from scapy.layers.l2 import Ether
from scapy.layers.inet import IP, UDP
from scapy.layers.vxlan import VXLAN


class TestVxlan(BridgeDomain, VppTestCase):
    """ VXLAN Test Case """

    def __init__(self, *args):
        BridgeDomain.__init__(self)
        VppTestCase.__init__(self, *args)

    def encapsulate(self, pkt):
        """
        Encapsulate the original payload frame by adding VXLAN header with its
        UDP, IP and Ethernet fields
        """
        return (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) /
                UDP(sport=self.dport, dport=self.dport, chksum=0) /
                VXLAN(vni=self.vni, flags=self.flags) /
                pkt)

    def decapsulate(self, pkt):
        """
        Decapsulate the original payload frame by removing VXLAN header
        """
        # check if is set I flag
        self.assertEqual(pkt[VXLAN].flags, int('0x8', 16))
        return pkt[VXLAN].payload

    # Method for checking VXLAN encapsulation.
    #
    def check_encapsulation(self, pkt):
        # TODO: add error messages
        # Verify source MAC is VPP_MAC and destination MAC is MY_MAC resolved
        #  by VPP using ARP.
        self.assertEqual(pkt[Ether].src, self.pg0.local_mac)
        self.assertEqual(pkt[Ether].dst, self.pg0.remote_mac)
        # Verify VXLAN tunnel source IP is VPP_IP and destination IP is MY_IP.
        self.assertEqual(pkt[IP].src, self.pg0.local_ip4)
        self.assertEqual(pkt[IP].dst, self.pg0.remote_ip4)
        # Verify UDP destination port is VXLAN 4789, source UDP port could be
        #  arbitrary.
        self.assertEqual(pkt[UDP].dport, type(self).dport)
        # TODO: checksum check
        # Verify VNI, based on configuration it must be 1.
        self.assertEqual(pkt[VXLAN].vni, type(self).vni)

    # Class method to start the VXLAN test case.
    #  Overrides setUpClass method in VppTestCase class.
    #  Python try..except statement is used to ensure that the tear down of
    #  the class will be executed even if exception is raised.
    #  @param cls The class pointer.
    @classmethod
    def setUpClass(cls):
        super(TestVxlan, cls).setUpClass()

        try:
            cls.dport = 4789
            cls.flags = 0x8
            cls.vni = 1

            # Create 2 pg interfaces.
            cls.create_pg_interfaces(range(2))
            cls.pg0.admin_up()
            cls.pg1.admin_up()

            # Configure IPv4 addresses on VPP pg0.
            cls.pg0.config_ip4()

            # Resolve MAC address for VPP's IP address on pg0.
            cls.pg0.resolve_arp()

            # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1
            #  into BD.
            r = cls.vapi.vxlan_add_del_tunnel(
                src_addr=cls.pg0.local_ip4n,
                dst_addr=cls.pg0.remote_ip4n,
                vni=cls.vni)
            cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=1)
            cls.vapi.sw_interface_set_l2_bridge(cls.pg1.sw_if_index, bd_id=1)
        except Exception:
            super(TestVxlan, cls).tearDownClass()
            raise

    # Method to define VPP actions before tear down of the test case.
    #  Overrides tearDown method in VppTestCase class.
    #  @param self The object pointer.
    def tearDown(self):
        super(TestVxlan, self).tearDown()
        if not self.vpp_dead:
            self.logger.info(self.vapi.cli("show bridge-domain 1 detail"))


if __name__ == '__main__':
    unittest.main(testRunner=VppTestRunner)
ass="n">vm); u32 hits = 0; u32 misses = 0; u32 chain_hits = 0; u32 drop = 0; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* First pass: compute hashes */ while (n_left_from > 2) { vlib_buffer_t *b0, *b1; u32 bi0, bi1; u8 *h0, *h1; u32 sw_if_index0, sw_if_index1; u32 table_index0, table_index1; vnet_classify_table_t *t0, *t1; /* Prefetch next iteration */ { vlib_buffer_t *p1, *p2; p1 = vlib_get_buffer (vm, from[1]); p2 = vlib_get_buffer (vm, from[2]); vlib_prefetch_buffer_header (p1, STORE); clib_prefetch_store (p1->data); vlib_prefetch_buffer_header (p2, STORE); clib_prefetch_store (p2->data); } bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); h0 = b0->data; bi1 = from[1]; b1 = vlib_get_buffer (vm, bi1); h1 = b1->data; sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; table_index0 = fcm->classify_table_index_by_sw_if_index[tid][sw_if_index0]; sw_if_index1 = vnet_buffer (b1)->sw_if_index[VLIB_RX]; table_index1 = fcm->classify_table_index_by_sw_if_index[tid][sw_if_index1]; t0 = pool_elt_at_index (vcm->tables, table_index0); t1 = pool_elt_at_index (vcm->tables, table_index1); vnet_buffer (b0)->l2_classify.hash = vnet_classify_hash_packet (t0, h0); vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash); vnet_buffer (b1)->l2_classify.hash = vnet_classify_hash_packet (t1, h1); vnet_classify_prefetch_bucket (t1, vnet_buffer (b1)->l2_classify.hash); vnet_buffer (b0)->l2_classify.table_index = table_index0; vnet_buffer (b1)->l2_classify.table_index = table_index1; from += 2; n_left_from -= 2; } while (n_left_from > 0) { vlib_buffer_t *b0; u32 bi0; u8 *h0; u32 sw_if_index0; u32 table_index0; vnet_classify_table_t *t0; bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); h0 = b0->data; sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; table_index0 = fcm->classify_table_index_by_sw_if_index[tid][sw_if_index0]; t0 = pool_elt_at_index (vcm->tables, table_index0); vnet_buffer (b0)->l2_classify.hash = vnet_classify_hash_packet (t0, h0); vnet_buffer (b0)->l2_classify.table_index = table_index0; vnet_classify_prefetch_bucket (t0, vnet_buffer (b0)->l2_classify.hash); from++; n_left_from--; } next_index = node->cached_next_index; from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; while (n_left_from > 0) { u32 n_left_to_next; vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); /* Not enough load/store slots to dual loop... */ while (n_left_from > 0 && n_left_to_next > 0) { u32 bi0; vlib_buffer_t *b0; u32 next0 = FLOW_CLASSIFY_NEXT_INDEX_DROP; u32 table_index0; vnet_classify_table_t *t0; vnet_classify_entry_t *e0; u64 hash0; u8 *h0; /* Stride 3 seems to work best */ if (PREDICT_TRUE (n_left_from > 3)) { vlib_buffer_t *p1 = vlib_get_buffer (vm, from[3]); vnet_classify_table_t *tp1; u32 table_index1; u64 phash1; table_index1 = vnet_buffer (p1)->l2_classify.table_index; if (PREDICT_TRUE (table_index1 != ~0)) { tp1 = pool_elt_at_index (vcm->tables, table_index1); phash1 = vnet_buffer (p1)->l2_classify.hash; vnet_classify_prefetch_entry (tp1, phash1); } } /* Speculatively enqueue b0 to the current next frame */ bi0 = from[0]; to_next[0] = bi0; from += 1; to_next += 1; n_left_from -= 1; n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); h0 = b0->data; table_index0 = vnet_buffer (b0)->l2_classify.table_index; e0 = 0; t0 = 0; vnet_get_config_data (fcm->vnet_config_main[tid], &b0->current_config_index, &next0, /* # bytes of config data */ 0); if (PREDICT_TRUE (table_index0 != ~0)) { hash0 = vnet_buffer (b0)->l2_classify.hash; t0 = pool_elt_at_index (vcm->tables, table_index0); e0 = vnet_classify_find_entry (t0, h0, hash0, now); if (e0) { hits++; } else { misses++; vnet_classify_add_del_session (vcm, table_index0, h0, ~0, 0, 0, 0, 0, 1); /* increment counter */ vnet_classify_find_entry (t0, h0, hash0, now); } } if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) && (b0->flags & VLIB_BUFFER_IS_TRACED))) { flow_classify_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); t->sw_if_index = vnet_buffer (b0)->sw_if_index[VLIB_RX]; t->next_index = next0; t->table_index = t0 ? t0 - vcm->tables : ~0; t->offset = (t0 && e0) ? vnet_classify_get_offset (t0, e0) : ~0; } /* Verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } vlib_node_increment_counter (vm, node->node_index, FLOW_CLASSIFY_ERROR_MISS, misses); vlib_node_increment_counter (vm, node->node_index, FLOW_CLASSIFY_ERROR_HIT, hits); vlib_node_increment_counter (vm, node->node_index, FLOW_CLASSIFY_ERROR_CHAIN_HIT, chain_hits); vlib_node_increment_counter (vm, node->node_index, FLOW_CLASSIFY_ERROR_DROP, drop); return frame->n_vectors; } VLIB_NODE_FN (ip4_flow_classify_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { return flow_classify_inline (vm, node, frame, FLOW_CLASSIFY_TABLE_IP4); } /* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip4_flow_classify_node) = { .name = "ip4-flow-classify", .vector_size = sizeof (u32), .format_trace = format_flow_classify_trace, .n_errors = ARRAY_LEN(flow_classify_error_strings), .error_strings = flow_classify_error_strings, .n_next_nodes = FLOW_CLASSIFY_NEXT_INDEX_N_NEXT, .next_nodes = { [FLOW_CLASSIFY_NEXT_INDEX_DROP] = "error-drop", }, }; /* *INDENT-ON* */ VLIB_NODE_FN (ip6_flow_classify_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) { return flow_classify_inline (vm, node, frame, FLOW_CLASSIFY_TABLE_IP6); } /* *INDENT-OFF* */ VLIB_REGISTER_NODE (ip6_flow_classify_node) = { .name = "ip6-flow-classify", .vector_size = sizeof (u32), .format_trace = format_flow_classify_trace, .n_errors = ARRAY_LEN(flow_classify_error_strings), .error_strings = flow_classify_error_strings, .n_next_nodes = FLOW_CLASSIFY_NEXT_INDEX_N_NEXT, .next_nodes = { [FLOW_CLASSIFY_NEXT_INDEX_DROP] = "error-drop", }, }; /* *INDENT-ON* */ static clib_error_t * flow_classify_init (vlib_main_t * vm) { flow_classify_main_t *fcm = &flow_classify_main; fcm->vlib_main = vm; fcm->vnet_main = vnet_get_main (); fcm->vnet_classify_main = &vnet_classify_main; return 0; } VLIB_INIT_FUNCTION (flow_classify_init); /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */