aboutsummaryrefslogtreecommitdiffstats
path: root/router/router/router.c
diff options
context:
space:
mode:
authorJeff Shaw <jeffrey.b.shaw@intel.com>2016-09-21 19:12:46 -0400
committerJeff Shaw <jeffrey.b.shaw@intel.com>2016-10-04 15:58:00 -0400
commitdfae7756baf895957a43944f63bfe0c850b16467 (patch)
treecb8b0c5ae0a09835f9817a8956bd86dbf9a1de57 /router/router/router.c
parent961580e47e58e9cb7175ec89703bc951c7ce71b2 (diff)
[router] IPv6 support and refactoring.
This change adds support for IPv6 while refactoring most of the original plugin code in the following ways. - Adhere to vpp style guidelines. - Split the netlink, node, and tap processing into separate files named with a "tap_inject" prefix which more accurately represents the functionality. - Implement our own tap management and rx/tx. This is to reduce the overhead of passing packets in and out of vnet tap devices, in favor of directly reading/writing from the tap. - Change how nodes work. Now we have neighbor, rx, and tx nodes. The neighbor node sends ARP replies and ICMP6 neighbor advertisements to the arp-input and icmp6-neighbor-solicitation nodes, respectively, before also injecting the packet to the host, making it possible for both vpp and the host network stack to resolve the next hop. The tx node injects packets into the host by writing to the tap. The rx node reads packets from the tap and sends them on its associated data plane interface. - Simplify the CLI. Instead of creating taps specifically for a given interface we create a tap for all of the Ethernet interfaces with the "enable tap-inject" CLI command. The interfaces are named with a "vpp" prefix, i.e. "vpp0". Also add a "disable tap-inject" option. - Provide ability to enable at configuration time with the tap-inject { enable } stanza. Change-Id: I6b56da606e2da1d793ce6aca222fe4eb5a4e070d Signed-off-by: Jeff Shaw <jeffrey.b.shaw@intel.com>
Diffstat (limited to 'router/router/router.c')
-rw-r--r--router/router/router.c691
1 files changed, 0 insertions, 691 deletions
diff --git a/router/router/router.c b/router/router/router.c
deleted file mode 100644
index 741f34c..0000000
--- a/router/router/router.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright 2016 Intel Corporation
- *
- * 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.
- */
-#include <net/ethernet.h>
-#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <vnet/vnet.h>
-#include <vnet/plugin/plugin.h>
-#include <vnet/ip/ip.h>
-#include <vnet/unix/tuntap.h>
-#include <librtnl/mapper.h>
-#include <vnet/ethernet/arp_packet.h>
-#include <vlibmemory/api.h>
-
-enum {
- NEXT_UNTAPPED = 0,
- NEXT_INJECT,
-};
-
-enum {
- ERROR_INJECT_ARP,
- ERROR_INJECT_ICMP,
- ERROR_INJECT_CLASSIFIED,
-};
-
-static char *error_strings[] = {
- [ERROR_INJECT_ARP] = "Inject ARP",
- [ERROR_INJECT_ICMP] = "Inject ICMP",
- [ERROR_INJECT_CLASSIFIED] = "Inject Classified",
-};
-
-struct tap_to_iface {
- u32 tap;
- u32 iface;
-};
-
-struct router_main {
- vnet_main_t *vnet_main;
- u32 *iface_to_tap;
- u32 *iface_to_protos;
- struct tap_to_iface *tap_to_iface;
- u32 ns_index;
-};
-
-static struct router_main rm;
-
-enum {
- PROTO_ARP = 0,
- PROTO_ICMP4,
- PROTO_IGMP4,
- PROTO_OSPF2,
- PROTO_TCP,
- PROTO_UDP,
- PROTO_N_TOTAL,
-};
-
-enum {
- PROTO_BIT_ARP = 1 << PROTO_ARP,
- PROTO_BIT_ICMP4 = 1 << PROTO_ICMP4,
- PROTO_BIT_IGMP4 = 1 << PROTO_IGMP4,
- PROTO_BIT_OSPF2 = 1 << PROTO_OSPF2,
- PROTO_BIT_TCP = 1 << PROTO_TCP,
- PROTO_BIT_UDP = 1 << PROTO_UDP,
-};
-
-static char *proto_strings[PROTO_N_TOTAL] = {
- [PROTO_ARP] = "arp",
- [PROTO_ICMP4] = "icmp4",
- [PROTO_IGMP4] = "igmp4",
- [PROTO_OSPF2] = "ospf2",
- [PROTO_TCP] = "tcp",
- [PROTO_UDP] = "udp",
-};
-
-static inline u32 parse_protos(char *proto_string)
-{
- u32 protos = 0;
- char *tok, **proto;
-
- for (tok = strtok(proto_string, ","); tok; tok = strtok(NULL, ","))
- for (proto = proto_strings; proto && *proto; ++proto)
- if (!strncmp(tok, *proto, 16))
- protos |= 1 << (proto - proto_strings);
- return protos;
-}
-
-static uword unformat_protos(unformat_input_t *input, va_list *args)
-{
- u32 *protos = va_arg(*args, u32 *);
- u8 *proto_string;
-
- if (unformat(input, "%s", &proto_string))
- *protos = parse_protos((char *)proto_string);
- return 1;
-}
-
-vlib_node_registration_t tap_inject_arp_node;
-vlib_node_registration_t tap_inject_icmp_node;
-vlib_node_registration_t tap_inject_classified_node;
-
-static inline void
-update_arp_entry(vlib_buffer_t *b0, ethernet_arp_header_t *arp, u32 vlib_rx)
-{
- ethernet_header_t *eth;
- ip4_address_t *if_addr;
- ip_interface_address_t *ifa;
-
- if (arp->l2_type != ntohs(ETHERNET_ARP_HARDWARE_TYPE_ethernet) ||
- arp->l3_type != ntohs(ETHERNET_TYPE_IP4))
- return;
-
- /* Check that IP address is local and matches incoming interface. */
- if_addr = ip4_interface_address_matching_destination(&ip4_main,
- &arp->ip4_over_ethernet[1].ip4,
- vlib_rx, &ifa);
- if (!if_addr)
- return;
-
- /* Source must also be local to subnet of matching interface address. */
- if (!ip4_destination_matches_interface(&ip4_main,
- &arp->ip4_over_ethernet[0].ip4, ifa))
- return;
-
- /* Reject replies with our local interface address. */
- if (if_addr->as_u32 == arp->ip4_over_ethernet[0].ip4.as_u32)
- return;
-
- if (if_addr->as_u32 != arp->ip4_over_ethernet[1].ip4.as_u32)
- return;
-
- eth = ethernet_buffer_get_header(b0);
-
- /* Trash ARP packets whose ARP-level source addresses do not
- * match their L2-frame-level source addresses */
- if (memcmp(eth->src_address, arp->ip4_over_ethernet[0].ethernet,
- sizeof(eth->src_address)))
- return;
-
- if (arp->ip4_over_ethernet[0].ip4.as_u32 == 0 ||
- (arp->ip4_over_ethernet[0].ip4.as_u32 ==
- arp->ip4_over_ethernet[1].ip4.as_u32))
- return;
-
- /* Learn or update sender's mapping only for requests or unicasts
- * that don't match local interface address. */
- if (ethernet_address_cast(eth->dst_address) != ETHERNET_ADDRESS_UNICAST)
- return;
-
- vnet_arp_set_ip4_over_ethernet(rm.vnet_main, vlib_rx, ~0,
- &arp->ip4_over_ethernet[0], 0);
-}
-
-static uword
-tap_inject_func(vlib_main_t *m, vlib_node_runtime_t *node, vlib_frame_t *f,
- int mode)
-{
- u32 n_left_from = f->n_vectors;
- u32 *from = vlib_frame_vector_args(f);
- u32 next_index = node->cached_next_index;
- u32 *to_next;
- u32 counter, count = 0;
-
- while (n_left_from) {
- vlib_buffer_t *b0;
- u32 next0, bi0, n_left;
- u32 vlib_rx, vlib_tx;
- u32 protos, proto_bit = 0;
-
- vlib_get_next_frame(m, node, next_index, to_next, n_left);
-
- *(to_next++) = bi0 = *(from++);
- --n_left_from;
- --n_left;
-
- b0 = vlib_get_buffer(m, bi0);
-
- vlib_rx = vnet_buffer(b0)->sw_if_index[VLIB_RX];
- vlib_tx = rm.iface_to_tap[vlib_rx];
- protos = rm.iface_to_protos[vlib_rx];
-
- next0 = NEXT_UNTAPPED;
-
- if (vlib_tx == 0 || vlib_tx == ~0 || protos == 0)
- goto untapped;
-
- if (mode == ERROR_INJECT_CLASSIFIED) {
- ip4_header_t *iphdr;
-
- iphdr = vlib_buffer_get_current(b0);
- if (iphdr->protocol == IP_PROTOCOL_TCP)
- proto_bit = PROTO_BIT_TCP;
- else if (iphdr->protocol == IP_PROTOCOL_UDP)
- proto_bit = PROTO_BIT_UDP;
- else if (iphdr->protocol == IP_PROTOCOL_OSPF)
- proto_bit = PROTO_BIT_OSPF2;
- else if (iphdr->protocol == IP_PROTOCOL_IGMP)
- proto_bit = PROTO_BIT_IGMP4;
- } else if (mode == ERROR_INJECT_ARP) {
- proto_bit = PROTO_BIT_ARP;
- } else if (mode == ERROR_INJECT_ICMP) {
- proto_bit = PROTO_BIT_ICMP4;
- }
-
- if (!(protos & proto_bit))
- goto untapped;
-
- next0 = NEXT_INJECT;
-
- vnet_buffer(b0)->sw_if_index[VLIB_TX] = vlib_tx;
- ++count;
-
- if (mode == ERROR_INJECT_ARP) {
- ethernet_arp_header_t *arphdr;
-
- arphdr = vlib_buffer_get_current(b0);
- if (arphdr->opcode == ntohs(ETHERNET_ARP_OPCODE_reply))
- update_arp_entry(b0, arphdr, vlib_rx);
- }
-
- /* FIXME: What about VLAN? */
- b0->current_data -= sizeof(ethernet_header_t);
- b0->current_length += sizeof(ethernet_header_t);
-
-untapped:
- vlib_validate_buffer_enqueue_x1(m, node, next_index, to_next,
- n_left, bi0, next0);
- vlib_put_next_frame(m, node, next_index, n_left);
- }
-
- switch (mode) {
- case ERROR_INJECT_ARP:
- counter = ERROR_INJECT_ARP;
- break;
- case ERROR_INJECT_ICMP:
- counter = ERROR_INJECT_ICMP;
- break;
- default:
- counter = ERROR_INJECT_CLASSIFIED;
- }
-
- vlib_node_increment_counter(m, node->node_index, counter, count);
- return f->n_vectors;
-}
-
-static uword
-tap_inject_arp(vlib_main_t *m, vlib_node_runtime_t *node, vlib_frame_t *f)
-{
- return tap_inject_func(m, node, f, ERROR_INJECT_ARP);
-}
-
-VLIB_REGISTER_NODE(tap_inject_arp_node) = {
- .function = tap_inject_arp,
- .name = "tap-inject-arp",
- .vector_size = sizeof(u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(error_strings),
- .error_strings = error_strings,
- .n_next_nodes = 2,
- .next_nodes = {
- [NEXT_UNTAPPED] = "arp-input",
- [NEXT_INJECT] = "interface-output",
- },
-};
-
-static uword
-tap_inject_icmp(vlib_main_t *m, vlib_node_runtime_t *node, vlib_frame_t *f)
-{
- return tap_inject_func(m, node, f, ERROR_INJECT_ICMP);
-}
-
-VLIB_REGISTER_NODE(tap_inject_icmp_node) = {
- .function = tap_inject_icmp,
- .name = "tap-inject-icmp",
- .vector_size = sizeof(u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(error_strings),
- .error_strings = error_strings,
- .n_next_nodes = 2,
- .next_nodes = {
- [NEXT_UNTAPPED] = "ip4-icmp-input",
- [NEXT_INJECT] = "interface-output",
- },
-};
-
-static uword
-tap_inject_classified(vlib_main_t *m, vlib_node_runtime_t *node,
- vlib_frame_t *f)
-{
- return tap_inject_func(m, node, f, ERROR_INJECT_CLASSIFIED);
-}
-
-VLIB_REGISTER_NODE(tap_inject_classified_node) = {
- .function = tap_inject_classified,
- .name = "tap-inject-classified",
- .vector_size = sizeof(u32),
- .type = VLIB_NODE_TYPE_INTERNAL,
- .n_errors = ARRAY_LEN(error_strings),
- .error_strings = error_strings,
- .n_next_nodes = 2,
- .next_nodes = {
- [NEXT_UNTAPPED] = "error-drop",
- [NEXT_INJECT] = "interface-output",
- },
-};
-
-static int
-set_tap_hwaddr(vlib_main_t *m, char *name, u8 *hwaddr)
-{
- int fd, rc;
- struct ifreq ifr;
-
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (fd < 0)
- return -1;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, (char *)name, sizeof(ifr.ifr_name) - 1);
- memcpy(ifr.ifr_hwaddr.sa_data, hwaddr, ETHER_ADDR_LEN);
- ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
- rc = ioctl(fd, SIOCSIFHWADDR, &ifr) < 0 ? -1 : 0;
- close(fd);
- return rc;
-}
-
-static int
-set_tap_link_state(vlib_main_t *m, char *name, u16 flags)
-{
- int fd, rc;
- struct ifreq ifr;
-
- fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (fd < 0)
- return -1;
-
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, (char *)name, sizeof(ifr.ifr_name) - 1);
-
- rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
- if (rc < 0)
- goto out;
-
- if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP)
- ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
- else
- ifr.ifr_flags &= ~(IFF_UP | IFF_RUNNING);
-
- rc = ioctl(fd, SIOCSIFFLAGS, &ifr) < 0 ? -1 : 0;
-out:
- close(fd);
- return rc;
-}
-
-static clib_error_t *
-do_tap_connect(vlib_main_t *m, char *name, u32 iface, u32 *tap)
-{
- vnet_hw_interface_t *hw = vnet_get_hw_interface(rm.vnet_main, iface);
- vnet_sw_interface_t *sw = vnet_get_sw_interface(rm.vnet_main, iface);
- u64 hw_address = 0;
-
- *tap = ~0;
- if (!hw)
- return clib_error_return(0, "invalid interface");
- else if (hw->hw_address)
- memcpy(&hw_address, hw->hw_address, 6);
-
- if (vnet_tap_connect(m, (u8 *)name, (u8 *)&hw_address, tap))
- return clib_error_return(0, "failed to connect tap");
-
- if (set_tap_hwaddr(m, name, (u8 *)&hw_address))
- return clib_error_return(0, "failed to set tap hw address");
-
- if (set_tap_link_state(m, name, sw->flags))
- return clib_error_return(0, "failed to set tap link state");
-
- if (set_int_l2_mode(m, rm.vnet_main, MODE_L2_XC, *tap, 0, 0, 0, iface))
- return clib_error_return(0, "failed to xconnect to interface");
-
- return vnet_sw_interface_set_flags(rm.vnet_main, *tap,
- VNET_SW_INTERFACE_FLAG_ADMIN_UP);
-}
-
-static void add_del_addr(ns_addr_t *a, int is_del)
-{
- struct tap_to_iface *map = NULL;
- u32 sw_if_index = ~0;
-
- vec_foreach(map, rm.tap_to_iface) {
- if (a->ifaddr.ifa_index == map->tap) {
- sw_if_index = map->iface;
- break;
- }
- }
-
- if (sw_if_index == ~0)
- return;
-
- ip4_add_del_interface_address(vlib_get_main(),
- sw_if_index, (ip4_address_t *)a->local,
- a->ifaddr.ifa_prefixlen, is_del);
-}
-
-static void add_del_route(ns_route_t *r, int is_del)
-{
- struct tap_to_iface *map = NULL;
- u32 sw_if_index = ~0;
-
- vec_foreach(map, rm.tap_to_iface) {
- if (r->oif == map->tap) {
- sw_if_index = map->iface;
- break;
- }
- }
-
- if (sw_if_index == ~0 || r->table != 254)
- return;
-
- ip4_add_del_route_next_hop(&ip4_main,
- is_del ? IP4_ROUTE_FLAG_DEL : IP4_ROUTE_FLAG_ADD,
- (ip4_address_t *)r->dst, r->rtm.rtm_dst_len,
- (ip4_address_t *)r->gateway, sw_if_index, 0, ~0, 0);
-}
-
-struct set_flags_args {
- u32 sw_if_index;
- u8 flags;
-};
-
-static void set_interface_flags_callback(struct set_flags_args *a)
-{
- vnet_sw_interface_set_flags(rm.vnet_main, a->sw_if_index,
- a->flags);
-}
-
-static void add_del_link(ns_link_t *l, int is_del)
-{
- struct tap_to_iface *map = NULL;
- u32 sw_if_index = ~0;
- u8 flags = 0;
- struct set_flags_args args;
- vnet_sw_interface_t *sw = NULL;
-
- vec_foreach(map, rm.tap_to_iface) {
- if (l->ifi.ifi_index == map->tap) {
- sw_if_index = map->iface;
- break;
- }
- }
-
- if (sw_if_index == ~0)
- return;
-
- sw = vnet_get_sw_interface(rm.vnet_main, sw_if_index);
- flags = sw->flags;
-
- if (l->ifi.ifi_flags & IFF_UP)
- flags |= VNET_SW_INTERFACE_FLAG_ADMIN_UP;
- else
- flags &= ~VNET_SW_INTERFACE_FLAG_ADMIN_UP;
-
- args.sw_if_index = sw_if_index;
- args.flags = flags;
-
- vl_api_rpc_call_main_thread(set_interface_flags_callback,
- (u8 *) &args, sizeof(args));
-}
-
-static void
-netns_notify_cb(void *obj, netns_type_t type, u32 flags, uword opaque)
-{
- if (type == NETNS_TYPE_ADDR)
- add_del_addr((ns_addr_t *)obj, flags & NETNS_F_DEL);
- else if (type == NETNS_TYPE_ROUTE)
- add_del_route((ns_route_t *)obj, flags & NETNS_F_DEL);
- else if (type == NETNS_TYPE_LINK)
- add_del_link((ns_link_t *)obj, flags & NETNS_F_DEL);
-}
-
-static void insert_tap_to_iface(u32 tap, u32 iface)
-{
- struct tap_to_iface map = {
- .tap = tap,
- .iface = iface,
- };
-
- vec_add1(rm.tap_to_iface, map);
-}
-
-
-static u32 ip4_next_index = ~0;
-
-static u32
-ip4_lookup_next_index(void)
-{
- if (ip4_next_index == ~0) {
- ip4_next_index = vlib_node_add_next(vlib_get_main(),
- ip4_lookup_node.index,
- tap_inject_classified_node.index);
- }
-
- return ip4_next_index;
-}
-
-static u32 ip4_multicast_arc_added;
-
-static void
-add_ip4_multicast_arc(void)
-{
- ip4_add_del_route_args_t a;
- ip_adjacency_t add_adj;
-
- if (ip4_multicast_arc_added)
- return;
-
- memset(&a, 0, sizeof(a));
- memset(&add_adj, 0, sizeof(add_adj));
-
- a.add_adj = &add_adj;
- a.n_add_adj = 1;
-
- a.flags = IP4_ROUTE_FLAG_TABLE_ID | IP4_ROUTE_FLAG_ADD;
- a.table_index_or_table_id = 0;
- a.dst_address.as_u32 = 0x000000E0; /* 224.0.0.0 */
- a.dst_address_length = 24;
- a.adj_index = ~0;
-
- add_adj.explicit_fib_index = ~0;
- add_adj.rewrite_header.node_index = ip4_rewrite_node.index;
- add_adj.lookup_next_index = ip4_lookup_next_index();
- add_adj.if_address_index = ~0;
-
- ip4_add_del_route(&ip4_main, &a);
- ip4_multicast_arc_added = 1;
-}
-
-static clib_error_t *
-tap_inject(vlib_main_t *m, unformat_input_t *input, vlib_cli_command_t *cmd)
-{
- char *name = NULL;
- u32 iface = ~0, tap = ~0, protos = 0;
- clib_error_t *err;
-
- while (unformat_check_input(input) != UNFORMAT_END_OF_INPUT) {
- if (unformat(input, "from %U", unformat_vnet_sw_interface,
- rm.vnet_main, &iface))
- ;
- else if (unformat(input, "as %s", &name))
- ;
- else if (unformat(input, "%U", unformat_protos, &protos))
- ;
- else
- break;
- }
-
- if (!protos)
- return clib_error_return(0,
- "no protocols specified");
- else if (iface == ~0)
- return clib_error_return(0,
- "interface name is missing or invalid");
- else if (!name)
- return clib_error_return(0,
- "host interface name is missing or invalid");
-
- if (protos & PROTO_BIT_OSPF2) {
- /* Require arp, icmp4, and igmp4 for ospf2. */
- if (!(protos & PROTO_BIT_ARP) ||
- !(protos & PROTO_BIT_ICMP4) ||
- !(protos & PROTO_BIT_IGMP4))
- return clib_error_return(0,
- "ospf2 requires arp, icmp4, and igmp4");
- }
-
- if (protos & PROTO_BIT_TCP) /* Require arp and icmp4 for tcp. */
- if (!(protos & PROTO_BIT_ARP) || !(protos & PROTO_BIT_ICMP4))
- return clib_error_return(0,
- "tcp requires arp and icmp4");
-
- if (protos & PROTO_BIT_UDP) {
- /* Require arp, icmp4, and igmp4 for udp. */
- if (!(protos & PROTO_BIT_ARP) ||
- !(protos & PROTO_BIT_ICMP4) ||
- !(protos & PROTO_BIT_IGMP4))
- return clib_error_return(0,
- "udp requires arp, icmp4, and igmp4");
- }
-
- err = do_tap_connect(m, name, iface, &tap);
- if (err) {
- if (tap != ~0)
- vnet_tap_delete(m, tap);
- return err;
- }
-
- if ((protos & PROTO_BIT_ARP) || (protos & PROTO_BIT_ICMP4)) {
- if (rm.ns_index == ~0) {
- char nsname = 0;
- netns_sub_t sub = {
- .notify = netns_notify_cb,
- .opaque = 0,
- };
-
- rm.ns_index = netns_open(&nsname, &sub);
- if (rm.ns_index == ~0) {
- vnet_tap_delete(m, tap);
- clib_error_return(0,
- "failed to open namespace");
- }
- }
- }
-
- if (protos & PROTO_BIT_IGMP4)
- add_ip4_multicast_arc();
-
- if (protos & PROTO_BIT_ARP)
- ethernet_register_input_type(m, ETHERNET_TYPE_ARP,
- tap_inject_arp_node.index);
-
- if (protos & PROTO_BIT_ICMP4)
- ip4_register_protocol(IP_PROTOCOL_ICMP,
- tap_inject_icmp_node.index);
-
- if (protos & PROTO_BIT_OSPF2)
- ip4_register_protocol(IP_PROTOCOL_OSPF,
- tap_inject_classified_node.index);
-
- if (protos & PROTO_BIT_TCP)
- ip4_register_protocol(IP_PROTOCOL_TCP,
- tap_inject_classified_node.index);
-
- if (protos & PROTO_BIT_UDP)
- ip4_register_protocol(IP_PROTOCOL_UDP,
- tap_inject_classified_node.index);
-
- /* Find sw_if_index of tap associated with data plane interface. */
- rm.iface_to_tap[iface] = tap;
- rm.iface_to_protos[iface] = protos;
-
- /* Find data plane interface associated with host tap ifindex. */
- insert_tap_to_iface(if_nametoindex(name), iface);
-
- return 0;
-}
-
-VLIB_CLI_COMMAND(tap_inject_command, static) = {
- .path = "tap inject",
- .short_help = "tap inject <protocol[,protocol...]> from <intfc-name> as <host-intfc-name>",
- .function = tap_inject,
-};
-
-static clib_error_t *
-interface_add_del(struct vnet_main_t *m, u32 hw_if_index, u32 add)
-{
- vnet_hw_interface_t *hw = vnet_get_hw_interface(m, hw_if_index);
- vnet_sw_interface_t *sw = vnet_get_sw_interface(m, hw->sw_if_index);
- ASSERT(hw->sw_if_index == sw->sw_if_index);
-
- vec_validate(rm.iface_to_tap, sw->sw_if_index);
- vec_validate(rm.iface_to_protos, sw->sw_if_index);
- rm.iface_to_tap[sw->sw_if_index] = ~0;
- rm.iface_to_protos[sw->sw_if_index] = 0;
- return 0;
-}
-VNET_HW_INTERFACE_ADD_DEL_FUNCTION(interface_add_del);
-
-clib_error_t *
-vlib_plugin_register(vlib_main_t *m, vnet_plugin_handoff_t *h, int f)
-{
- rm.vnet_main = h->vnet_main;
- rm.ns_index = ~0;
- return 0;
-}
-
-static clib_error_t *router_init(vlib_main_t *m)
-{
- return 0;
-}
-VLIB_INIT_FUNCTION(router_init);