- if (mp->enable_disable)
- si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
- else
- si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
-
- BAD_SW_IF_INDEX_LABEL;
-
- out:
- REPLY_MACRO(VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
-}
-
-static void
-vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t *mp, vlib_main_t * vm)
-{
- vl_api_ip_neighbor_add_del_reply_t * rmp;
- vnet_main_t * vnm = vnet_get_main();
- u32 fib_index;
- int rv=0;
- stats_main_t * sm = &stats_main;
-
- VALIDATE_SW_IF_INDEX(mp);
-
- dslock (sm, 1 /* release hint */, 7 /* tag */);
-
- if (mp->is_ipv6) {
- if (mp->is_add)
- rv = vnet_set_ip6_ethernet_neighbor
- (vm, ntohl(mp->sw_if_index),
- (ip6_address_t *)(mp->dst_address),
- mp->mac_address, sizeof (mp->mac_address), mp->is_static);
- else
- rv = vnet_unset_ip6_ethernet_neighbor
- (vm, ntohl(mp->sw_if_index),
- (ip6_address_t *)(mp->dst_address),
- mp->mac_address, sizeof(mp->mac_address));
- } else {
- ip4_main_t * im = &ip4_main;
- ip_lookup_main_t * lm = &im->lookup_main;
- ethernet_arp_ip4_over_ethernet_address_t a;
- u32 ai;
- ip_adjacency_t *nh_adj;
-
- uword * p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id));
- if (! p) {
- rv = VNET_API_ERROR_NO_SUCH_FIB;
- goto out;
- }
- fib_index = p[0];
-
- /*
- * Unfortunately, folks have a penchant for
- * adding interface addresses to the ARP cache, and
- * wondering why the forwarder eventually ASSERTs...
- */
- ai = ip4_fib_lookup_with_table
- (im, fib_index, (ip4_address_t *)(mp->dst_address),
- 1 /* disable default route */);
-
- if (ai != 0) {
- nh_adj = ip_get_adjacency (lm, ai);
- /* Never allow manipulation of a local adj! */
- if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL) {
- clib_warning("%U matches local adj",
- format_ip4_address,
- (ip4_address_t *)(mp->dst_address));
- rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
- goto out;
- }
- }
-
- clib_memcpy (&a.ethernet, mp->mac_address, 6);
- clib_memcpy (&a.ip4, mp->dst_address, 4);
-
- if (mp->is_add)
- rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
- fib_index, &a, mp->is_static);
- else
- rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl(mp->sw_if_index),
- fib_index, &a);
- }
-
- BAD_SW_IF_INDEX_LABEL;
- out:
- dsunlock (sm);
- REPLY_MACRO(VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
-}
-
-static void
-vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t *mp)
+ BAD_SW_IF_INDEX_LABEL;
+
+out:
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2(VL_API_CREATE_SUBIF_REPLY,
+ ({
+ rmp->sw_if_index = ntohl(sw_if_index);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+vl_api_mpls_gre_add_del_tunnel_t_handler (vl_api_mpls_gre_add_del_tunnel_t *
+ mp)
+{
+ vl_api_mpls_gre_add_del_tunnel_reply_t *rmp;
+ int rv = 0;
+ stats_main_t *sm = &stats_main;
+ u32 tunnel_sw_if_index = ~0;
+
+ dslock (sm, 1 /* release hint */ , 5 /* tag */ );
+
+ rv = vnet_mpls_gre_add_del_tunnel ((ip4_address_t *) (mp->src_address),
+ (ip4_address_t *) (mp->dst_address),
+ (ip4_address_t *) (mp->intfc_address),
+ (u32) (mp->intfc_address_length),
+ ntohl (mp->inner_vrf_id),
+ ntohl (mp->outer_vrf_id),
+ &tunnel_sw_if_index,
+ mp->l2_only, mp->is_add);
+ dsunlock (sm);
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2(VL_API_MPLS_GRE_ADD_DEL_TUNNEL_REPLY,
+ ({
+ rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+ vl_api_mpls_ethernet_add_del_tunnel_t_handler
+ (vl_api_mpls_ethernet_add_del_tunnel_t * mp)
+{
+ vl_api_mpls_ethernet_add_del_tunnel_reply_t *rmp;
+ int rv = 0;
+ stats_main_t *sm = &stats_main;
+ u32 tunnel_sw_if_index;
+
+ dslock (sm, 1 /* release hint */ , 5 /* tag */ );
+
+ rv = vnet_mpls_ethernet_add_del_tunnel
+ (mp->dst_mac_address, (ip4_address_t *) (mp->adj_address),
+ (u32) (mp->adj_address_length), ntohl (mp->vrf_id),
+ ntohl (mp->tx_sw_if_index),
+ &tunnel_sw_if_index, mp->l2_only, mp->is_add);
+
+ dsunlock (sm);
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO2(VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_REPLY,
+ ({
+ rmp->tunnel_sw_if_index = ntohl(tunnel_sw_if_index);
+ }));
+ /* *INDENT-ON* */
+}
+
+/*
+ * This piece of misery brought to you because the control-plane
+ * can't figure out the tx interface + dst-mac address all by itself
+ */
+static int mpls_ethernet_add_del_tunnel_2_t_handler
+ (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp)
+{
+ pending_route_t *pr;
+ vl_api_mpls_ethernet_add_del_tunnel_2_t *pme;
+ vnet_main_t *vnm = vnet_get_main ();
+ vlib_main_t *vm = vlib_get_main ();
+ stats_main_t *sm = &stats_main;
+ vpe_api_main_t *vam = &vpe_api_main;
+ u32 inner_fib_index, outer_fib_index;
+ ip4_main_t *im = &ip4_main;
+ ip_lookup_main_t *lm = &im->lookup_main;
+ ip_adjacency_t *adj = 0;
+ u32 lookup_result;
+ u32 tx_sw_if_index;
+ u8 *dst_mac_address;
+ clib_error_t *e;
+ uword *p;
+ int rv;
+ u32 tunnel_sw_if_index;
+
+ p = hash_get (im->fib_index_by_table_id, ntohl (mp->outer_vrf_id));
+ if (!p)
+ return VNET_API_ERROR_NO_SUCH_FIB;
+ else
+ outer_fib_index = p[0];
+
+
+ p = hash_get (im->fib_index_by_table_id, ntohl (mp->inner_vrf_id));
+ if (!p)
+ return VNET_API_ERROR_NO_SUCH_INNER_FIB;
+ else
+ inner_fib_index = p[0];
+
+ if (inner_fib_index == outer_fib_index)
+ return VNET_API_ERROR_INVALID_VALUE;
+
+ lookup_result = ip4_fib_lookup_with_table
+ (im, outer_fib_index,
+ (ip4_address_t *) mp->next_hop_ip4_address_in_outer_vrf,
+ 1 /* disable default route */ );
+
+ adj = ip_get_adjacency (lm, lookup_result);
+ tx_sw_if_index = adj->rewrite_header.sw_if_index;
+
+ if (mp->is_add && mp->resolve_if_needed)
+ {
+ if (adj->lookup_next_index == IP_LOOKUP_NEXT_ARP)
+ {
+ pool_get (vam->pending_routes, pr);
+ pr->resolve_type = RESOLVE_MPLS_ETHERNET_ADD_DEL;
+ pme = &pr->t;
+ clib_memcpy (pme, mp, sizeof (*pme));
+ /* recursion block, "just in case" */
+ pme->resolve_if_needed = 0;
+ pme->resolve_attempts = ntohl (mp->resolve_attempts);
+ pme->resolve_opaque = tx_sw_if_index;
+ vnet_register_ip4_arp_resolution_event
+ (vnm,
+ (ip4_address_t *) & (pme->next_hop_ip4_address_in_outer_vrf),
+ vpe_resolver_process_node.index,
+ RESOLUTION_EVENT, pr - vam->pending_routes);
+
+ vlib_process_signal_event
+ (vm, vpe_resolver_process_node.index,
+ RESOLUTION_PENDING_EVENT, 0 /* data */ );
+
+ /* The interface may be down, etc. */
+ e = ip4_probe_neighbor
+ (vm, (ip4_address_t *) & (mp->next_hop_ip4_address_in_outer_vrf),
+ tx_sw_if_index);
+
+ if (e)
+ clib_error_report (e);
+
+ return VNET_API_ERROR_IN_PROGRESS;
+ }
+ }
+
+ if (adj->lookup_next_index != IP_LOOKUP_NEXT_REWRITE)
+ return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB;
+
+ dst_mac_address =
+ vnet_rewrite_get_data_internal
+ (&adj->rewrite_header, sizeof (adj->rewrite_data));
+
+ dslock (sm, 1 /* release hint */ , 10 /* tag */ );
+
+ rv = vnet_mpls_ethernet_add_del_tunnel
+ (dst_mac_address, (ip4_address_t *) (mp->adj_address),
+ (u32) (mp->adj_address_length), ntohl (mp->inner_vrf_id),
+ tx_sw_if_index, &tunnel_sw_if_index, mp->l2_only, mp->is_add);
+
+ dsunlock (sm);
+
+ return rv;
+}
+
+static void
+ vl_api_mpls_ethernet_add_del_tunnel_2_t_handler
+ (vl_api_mpls_ethernet_add_del_tunnel_2_t * mp)
+{
+ vl_api_mpls_ethernet_add_del_tunnel_reply_t *rmp;
+ int rv = 0;
+
+ rv = mpls_ethernet_add_del_tunnel_2_t_handler (mp);
+
+ REPLY_MACRO (VL_API_MPLS_ETHERNET_ADD_DEL_TUNNEL_2_REPLY);
+}
+
+
+static void
+vl_api_mpls_add_del_encap_t_handler (vl_api_mpls_add_del_encap_t * mp)
+{
+ vl_api_mpls_add_del_encap_reply_t *rmp;
+ int rv;
+ static u32 *labels;
+ int i;
+
+ vec_reset_length (labels);
+
+ for (i = 0; i < mp->nlabels; i++)
+ vec_add1 (labels, ntohl (mp->labels[i]));
+
+ /* $$$$ fixme */
+ rv = vnet_mpls_add_del_encap ((ip4_address_t *) mp->dst_address,
+ ntohl (mp->vrf_id), labels,
+ ~0 /* policy_tunnel_index */ ,
+ 0 /* no_dst_hash */ ,
+ 0 /* indexp */ ,
+ mp->is_add);
+
+ REPLY_MACRO (VL_API_MPLS_ADD_DEL_ENCAP_REPLY);
+}
+
+static void
+vl_api_mpls_add_del_decap_t_handler (vl_api_mpls_add_del_decap_t * mp)
+{
+ vl_api_mpls_add_del_decap_reply_t *rmp;
+ int rv;
+
+ rv = vnet_mpls_add_del_decap (ntohl (mp->rx_vrf_id), ntohl (mp->tx_vrf_id),
+ ntohl (mp->label), ntohl (mp->next_index),
+ mp->s_bit, mp->is_add);
+
+ REPLY_MACRO (VL_API_MPLS_ADD_DEL_DECAP_REPLY);
+}
+
+static void
+vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
+{
+ vl_api_proxy_arp_add_del_reply_t *rmp;
+ u32 fib_index;
+ int rv;
+ ip4_main_t *im = &ip4_main;
+ stats_main_t *sm = &stats_main;
+ int vnet_proxy_arp_add_del (ip4_address_t * lo_addr,
+ ip4_address_t * hi_addr,
+ u32 fib_index, int is_del);
+ uword *p;
+
+ dslock (sm, 1 /* release hint */ , 6 /* tag */ );
+
+ p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
+
+ if (!p)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto out;
+ }
+
+ fib_index = p[0];
+
+ rv = vnet_proxy_arp_add_del ((ip4_address_t *) mp->low_address,
+ (ip4_address_t *) mp->hi_address,
+ fib_index, mp->is_add == 0);
+
+out:
+ dsunlock (sm);
+ REPLY_MACRO (VL_API_PROXY_ARP_ADD_DEL_REPLY);
+}
+
+static void
+ vl_api_proxy_arp_intfc_enable_disable_t_handler
+ (vl_api_proxy_arp_intfc_enable_disable_t * mp)
+{
+ int rv = 0;
+ vnet_main_t *vnm = vnet_get_main ();
+ vl_api_proxy_arp_intfc_enable_disable_reply_t *rmp;
+ vnet_sw_interface_t *si;
+ u32 sw_if_index;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ sw_if_index = ntohl (mp->sw_if_index);
+
+ if (pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
+ {
+ rv = VNET_API_ERROR_INVALID_SW_IF_INDEX;
+ goto out;
+ }
+
+ si = vnet_get_sw_interface (vnm, sw_if_index);
+
+ ASSERT (si);
+
+ if (mp->enable_disable)
+ si->flags |= VNET_SW_INTERFACE_FLAG_PROXY_ARP;
+ else
+ si->flags &= ~VNET_SW_INTERFACE_FLAG_PROXY_ARP;
+
+ BAD_SW_IF_INDEX_LABEL;
+
+out:
+ REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
+}
+
+static void
+vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
+ vlib_main_t * vm)
+{
+ vl_api_ip_neighbor_add_del_reply_t *rmp;
+ vnet_main_t *vnm = vnet_get_main ();
+ u32 fib_index;
+ int rv = 0;
+ stats_main_t *sm = &stats_main;
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ dslock (sm, 1 /* release hint */ , 7 /* tag */ );
+
+ if (mp->is_ipv6)
+ {
+ if (mp->is_add)
+ rv = vnet_set_ip6_ethernet_neighbor
+ (vm, ntohl (mp->sw_if_index),
+ (ip6_address_t *) (mp->dst_address),
+ mp->mac_address, sizeof (mp->mac_address), mp->is_static);
+ else
+ rv = vnet_unset_ip6_ethernet_neighbor
+ (vm, ntohl (mp->sw_if_index),
+ (ip6_address_t *) (mp->dst_address),
+ mp->mac_address, sizeof (mp->mac_address));
+ }
+ else
+ {
+ ip4_main_t *im = &ip4_main;
+ ip_lookup_main_t *lm = &im->lookup_main;
+ ethernet_arp_ip4_over_ethernet_address_t a;
+ u32 ai;
+ ip_adjacency_t *nh_adj;
+
+ uword *p = hash_get (im->fib_index_by_table_id, ntohl (mp->vrf_id));
+ if (!p)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto out;
+ }
+ fib_index = p[0];
+
+ /*
+ * Unfortunately, folks have a penchant for
+ * adding interface addresses to the ARP cache, and
+ * wondering why the forwarder eventually ASSERTs...
+ */
+ ai = ip4_fib_lookup_with_table
+ (im, fib_index, (ip4_address_t *) (mp->dst_address),
+ 1 /* disable default route */ );
+
+ if (ai != 0)
+ {
+ nh_adj = ip_get_adjacency (lm, ai);
+ /* Never allow manipulation of a local adj! */
+ if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_LOCAL)
+ {
+ clib_warning ("%U matches local adj",
+ format_ip4_address,
+ (ip4_address_t *) (mp->dst_address));
+ rv = VNET_API_ERROR_ADDRESS_MATCHES_INTERFACE_ADDRESS;
+ goto out;
+ }
+ }
+
+ clib_memcpy (&a.ethernet, mp->mac_address, 6);
+ clib_memcpy (&a.ip4, mp->dst_address, 4);
+
+ if (mp->is_add)
+ rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
+ fib_index, &a, mp->is_static);
+ else
+ rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index),
+ fib_index, &a);
+ }
+
+ BAD_SW_IF_INDEX_LABEL;
+out:
+ dsunlock (sm);
+ REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
+}
+
+static void
+vl_api_is_address_reachable_t_handler (vl_api_is_address_reachable_t * mp)