/* * Copyright (c) 2016 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. */ /** * @file * @brief Local TCP/IP stack punt infrastructure. * * Provides a set of VPP nodes together with the relevant APIs and CLI * commands in order to adjust and dispatch packets from the VPP data plane * to the local TCP/IP stack */ #include #include #include #include #include #include #include #include #include #include #include #include punt_main_t punt_main; char * vnet_punt_get_server_pathname (void) { punt_main_t *pm = &punt_main; return pm->sun_path; } static void punt_client_l4_db_add (ip_address_family_t af, u16 port, u32 index) { punt_main_t *pm = &punt_main; pm->db.clients_by_l4_port = hash_set (pm->db.clients_by_l4_port, punt_client_l4_mk_key (af, port), index); } static u32 punt_client_l4_db_remove (ip_address_family_t af, u16 port) { punt_main_t *pm = &punt_main; u32 key, index = ~0; uword *p; key = punt_client_l4_mk_key (af, port); p = hash_get (pm->db.clients_by_l4_port, key); if (p) index = p[0]; hash_unset (pm->db.clients_by_l4_port, key); return (index); } static void punt_client_ip_proto_db_add (ip_address_family_t af, ip_protocol_t proto, u32 index) { punt_main_t *pm = &punt_main; pm->db.clients_by_ip_proto = hash_set (pm->db.clients_by_ip_proto, punt_client_ip_proto_mk_key (af, proto), index); } static u32 punt_client_ip_proto_db_remove (ip_address_family_t af, ip_protocol_t proto) { punt_main_t *pm = &punt_main; u32 key, index = ~0; uword *p; key = punt_client_ip_proto_mk_key (af, proto); p = hash_get (pm->db.clients_by_ip_proto, key); if (p) index = p[0]; hash_unset (pm->db.clients_by_ip_proto, key); return (index); } static void punt_client_exception_db_add (vlib_punt_reason_t reason, u32 pci) { punt_main_t *pm = &punt_main; vec_validate_init_empty (pm->db.clients_by_exception, reason, ~0); pm->db.clients_by_exception[reason] = pci; } static u32 punt_client_exception_db_remove (vlib_punt_reason_t reason) { punt_main_t *pm = &punt_main; u32 pci = ~0; if (punt_client_exception_get (reason)) { pci = pm->db.clients_by_exception[reason]; pm->db.clients_by_exception[reason] = ~0; } return pci; } static clib_error_t * punt_socket_read_ready (clib_file_t * uf) { vlib_main_t *vm = vlib_get_main (); punt_main_t *pm = &punt_main; /** Schedule the rx node */ vlib_node_set_interrupt_pending (vm, punt_socket_rx_node.index); vec_add1 (pm->ready_fds, uf->file_descriptor); return 0; } static clib_error_t * punt_socket_register_l4 (vlib_main_t * vm, ip_address_family_t af, u8 protocol, u16 port, char *client_pathname) { punt_main_t *pm = &punt_main; punt_client_t *c; /* For now we only support UDP punt */ if (protocol != IP_PROTOCOL_UDP) return clib_error_return (0, "only UDP protocol (%d) is supported, got %d", IP_PROTOCOL_UDP, protocol); if (port == (u16) ~ 0) return clib_error_return (0, "UDP port number required"); c = punt_client_l4_get (af, port); if (NULL == c) { pool_get_zero (pm->punt_client_pool, c); punt_client_l4_db_add (af, port, c - pm->punt_client_pool); } memcpy (c->caddr.sun_path, client_pathname, sizeof (c->caddr.sun_path)); c->caddr.sun_family = AF_UNIX; c->reg.type = PUNT_TYPE_L4; c->reg.punt.l4.port = port; c->reg.punt.l4.protocol = protocol; c->reg.punt.l4.af = af; u32 node_index = (af == AF_IP4 ? udp4_punt_socket_node.index : udp6_punt_socket_node.index); udp_register_dst_port (vm, port, node_index, af == AF_IP4); return (NULL); } static clib_error_t * punt_socket_register_ip_proto (vlib_main_t * vm, ip_address_family_t af, ip_protocol_t proto, char *client_pathname) { punt_main_t *pm = &punt_main; punt_client_t *c; c = punt_client_ip_proto_get (af, proto); if (NULL == c) { pool_get_zero (pm->punt_client_pool, c); punt_client_ip_proto_db_add (af, proto, c - pm->punt_client_pool); } memcpy (c->caddr.sun_path, client_pathname, sizeof (c->caddr.sun_path)); c->caddr.sun_family = AF_UNIX; c->reg.type = PUNT_TYPE_IP_PROTO; c->reg.punt.ip_proto.protocol = proto; c->reg.punt.ip_proto.af = af; if (af == AF_IP4) ip4_register_protocol (proto, ip4_proto_punt_socket_node.index); else ip6_register_protocol (proto, ip6_proto_punt_socket_node.index); return (NULL); } static clib_error_t * punt_socket_register_exception (vlib_main_t * vm, vlib_punt_reason_t reason, char *client_pathname) { punt_main_t *pm = &punt_main; punt_client_t *pc; pc = punt_client_exception_get (reason); if (NULL == pc) { pool_get_zero (pm->punt_client_pool, pc); punt_client_exception_db_add (reason, pc - pm->punt_client_pool); } memcpy (pc->caddr.sun_path, client_pathname, sizeof (pc->caddr.sun_path)); pc->caddr.sun_family = AF_UNIX; pc->reg.type = PUNT_TYPE_EXCEPTION; pc->reg.punt.exception.reason = reason; vlib_punt_register (pm->hdl, pc->reg.punt.exception.reason, "exception-punt-socket"); return (NULL); } static clib_error_t * punt_socket_unregister_l4 (ip_address_family_t af, ip_protocol_t protocol, u16 port) { u32 pci; udp_unregister_dst_port (vlib_get_main (), port, af == AF_IP4); pci = punt_client_l4_db_remove (af, port); if (~0 != pci) pool_put_index (punt_main.punt_client_pool, pci); return (NULL); } static clib_error_t * punt_socket_unregister_ip_proto (ip_address_family_t af, ip_protocol_t proto) { u32 pci; if (af == AF_IP4) ip4_unregister_protocol (proto); else ip6_unregister_protocol (proto); pci = punt_client_ip_proto_db_remove (af, proto); if (~0 != pci) pool_put_index (punt_main.punt_client_pool, pci); return (NULL); } static clib_error_t * punt_socket_unregister_exception (vlib_punt_reason_t reason) { u32 pci; pci = punt_client_exception_db_remove (reason); if (~0 != pci) pool_put_index (punt_main.punt_client_pool, pci); return (NULL); } clib_error_t * vnet_punt_socket_add (vlib_main_t * vm, u32 header_version, const punt_reg_t * pr, char *client_pathname) { punt_main_t *pm = &punt_main; if (!pm->is_configured) return clib_error_return (0, "socket is not configured"); if (header_version != PUNT_PACKETDESC_VERSION) return clib_error_return (0, "Invalid packet descriptor version"); if (strncmp (client_pathname, vnet_punt_get_server_pathname (), UNIX_PATH_MAX) == 0) return clib_error_return (0, "Punt socket: Invalid client path: %s", client_pathname); /* Register client */ switch (pr->type) { case PUNT_TYPE_L4: return (punt_socket_register_l4 (vm, pr->punt.l4.af, pr->punt.l4.protocol, pr->punt.l4.port, client_pathname)); case PUNT_TYPE_IP_PROTO: return (punt_socket_register_ip_proto (vm, pr->punt.ip_proto.af, pr->punt.ip_proto.protocol, client_pathname)); case PUNT_TYPE_EXCEPTION: return (punt_socket_register_exception (vm, pr->punt.exception.reason, client_pathname)); } return 0; } clib_error_t * vnet_punt_socket_del (vlib_main_t * vm, const punt_reg_t * pr) { punt_main_t *pm = &punt_main; if (!pm->is_configured) return clib_error_return (0, "socket is not configured"); switch (pr->type) { case PUNT_TYPE_L4: return (punt_socket_unregister_l4 (pr->punt.l4.af, pr->punt.l4.protocol, pr->punt.l4.port)); case PUNT_TYPE_IP_PROTO: return (punt_socket_unregister_ip_proto (pr->punt.ip_proto.af, pr->punt.ip_proto.protocol)); case PUNT_TYPE_EXCEPTION: return (punt_socket_unregister_exception (pr->punt.exception.reason)); } return 0; } /** * @brief Request IP traffic punt to the local TCP/IP stack. * * @em Note * - UDP and TCP are the only protocols supported in the current implementation * * @param vm vlib_main_t corresponding to the current thread * @param af IP address family. * @param protocol 8-bits L4 protocol value * UDP is 17 * TCP is 1 * @param port 16-bits L4 (TCP/IP) port number when applicable (UDP only) * * @returns 0 on success, non-zero value otherwise */ static clib_error_t * punt_l4_add_del (vlib_main_t * vm, ip_address_family_t af, ip_protocol_t protocol, u16 port, bool is_add) { /* For now we only support TCP and UDP punt */ if (protocol != IP_PROTOCOL_UDP && protocol != IP_PROTOCOL_TCP) return clib_error_return (0, "only UD
#!/usr/bin/env python

import unittest

from framework import VppTestCase, VppTestRunner, running_extended_tests
from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath


class TestMactime(VppTestCase):
    """ Mactime Unit Test Cases """

    @classmethod
    def setUpClass(cls):
        super(TestMactime, cls).setUpClass()

    @classmethod
    def tearDownClass(cls):
        super(TestMactime, cls).tearDownClass()

    def setUp(self):
        super(TestMactime, self).setUp()

    def tearDown(self):
        super(TestMactime