IP unnumbered dump
[vpp.git] / src / vnet / ip / ip_api.c
index 9cd6257..ce3ff79 100644 (file)
@@ -25,6 +25,7 @@
 #include <vnet/api_errno.h>
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/ip/ip.h>
+#include <vnet/ip/ip_neighbor.h>
 #include <vnet/ip/ip6_neighbor.h>
 #include <vnet/fib/fib_table.h>
 #include <vnet/fib/fib_api.h>
@@ -73,11 +74,15 @@ _(IP_NEIGHBOR_DUMP, ip_neighbor_dump)                                   \
 _(IP_MROUTE_ADD_DEL, ip_mroute_add_del)                                 \
 _(MFIB_SIGNAL_DUMP, mfib_signal_dump)                                   \
 _(IP_ADDRESS_DUMP, ip_address_dump)                                     \
+_(IP_UNNUMBERED_DUMP, ip_unnumbered_dump)                               \
 _(IP_DUMP, ip_dump)                                                     \
 _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del)                             \
 _(SET_ARP_NEIGHBOR_LIMIT, set_arp_neighbor_limit)                      \
+_(IP_PROBE_NEIGHBOR, ip_probe_neighbor)                                \
+_(IP_SCAN_NEIGHBOR_ENABLE_DISABLE, ip_scan_neighbor_enable_disable)     \
 _(WANT_IP4_ARP_EVENTS, want_ip4_arp_events)                             \
 _(WANT_IP6_ND_EVENTS, want_ip6_nd_events)                               \
+_(WANT_IP6_RA_EVENTS, want_ip6_ra_events)                               \
 _(PROXY_ARP_ADD_DEL, proxy_arp_add_del)                                 \
 _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable)       \
 _(RESET_FIB, reset_fib)                                                        \
@@ -90,6 +95,7 @@ _(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config)           \
 _(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix)           \
 _(IP6ND_PROXY_ADD_DEL, ip6nd_proxy_add_del)                             \
 _(IP6ND_PROXY_DUMP, ip6nd_proxy_dump)                                   \
+_(IP6ND_SEND_ROUTER_SOLICITATION, ip6nd_send_router_solicitation)       \
 _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable )    \
 _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS,                             \
   sw_interface_ip6_set_link_local_address)                             \
@@ -101,7 +107,8 @@ _(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL,                               \
 _(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL,                     \
   ip_source_and_port_range_check_interface_add_del)                     \
 _(IP_REASSEMBLY_SET, ip_reassembly_set)                                 \
-_(IP_REASSEMBLY_GET, ip_reassembly_get)
+_(IP_REASSEMBLY_GET, ip_reassembly_get)                                 \
+_(IP_REASSEMBLY_ENABLE_DISABLE, ip_reassembly_enable_disable)
 
 extern void stats_dslock_with_hint (int hint, int tag);
 extern void stats_dsunlock (void);
@@ -1204,13 +1211,15 @@ mroute_add_del_handler (u8 is_add,
                        dpo_proto_t nh_proto,
                        u32 entry_flags,
                        fib_rpf_id_t rpf_id,
-                       u32 next_hop_sw_if_index, u32 itf_flags, u32 bier_imp)
+                       u32 next_hop_sw_if_index,
+                       ip46_address_t * nh, u32 itf_flags, u32 bier_imp)
 {
   stats_dslock_with_hint (1 /* release hint */ , 2 /* tag */ );
 
   fib_route_path_t path = {
     .frp_sw_if_index = next_hop_sw_if_index,
     .frp_proto = nh_proto,
+    .frp_addr = *nh,
   };
 
   if (is_local)
@@ -1249,6 +1258,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
 {
   fib_protocol_t fproto;
   dpo_proto_t nh_proto;
+  ip46_address_t nh;
   u32 fib_index;
   int rv;
 
@@ -1273,6 +1283,8 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
                   sizeof (pfx.fp_grp_addr.ip4));
       clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address,
                   sizeof (pfx.fp_src_addr.ip4));
+      memset (&nh.ip6, 0, sizeof (nh.ip6));
+      clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4));
     }
   else
     {
@@ -1280,6 +1292,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
                   sizeof (pfx.fp_grp_addr.ip6));
       clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address,
                   sizeof (pfx.fp_src_addr.ip6));
+      clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6));
     }
 
   return (mroute_add_del_handler (mp->is_add,
@@ -1289,6 +1302,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
                                  ntohl (mp->entry_flags),
                                  ntohl (mp->rpf_id),
                                  ntohl (mp->next_hop_sw_if_index),
+                                 &nh,
                                  ntohl (mp->itf_flags),
                                  ntohl (mp->bier_imp)));
 }
@@ -1382,8 +1396,11 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
   if (mp->is_ipv6)
     {
       /* *INDENT-OFF* */
-      foreach_ip_interface_address (lm6, ia, sw_if_index,
-                                    1 /* honor unnumbered */,
+      /* Do not send subnet details of the IP-interface for
+       * unnumbered interfaces. otherwise listening clients
+       * will be confused that the subnet is applied on more
+       * than one interface */
+      foreach_ip_interface_address (lm6, ia, sw_if_index, 0,
       ({
         r6 = ip_interface_address_get_address (lm6, ia);
         u16 prefix_length = ia->address_length;
@@ -1395,8 +1412,7 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
   else
     {
       /* *INDENT-OFF* */
-      foreach_ip_interface_address (lm4, ia, sw_if_index,
-                                    1 /* honor unnumbered */,
+      foreach_ip_interface_address (lm4, ia, sw_if_index, 0,
       ({
         r4 = ip_interface_address_get_address (lm4, ia);
         u16 prefix_length = ia->address_length;
@@ -1408,6 +1424,74 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp)
   BAD_SW_IF_INDEX_LABEL;
 }
 
+static void
+send_ip_unnumbered_details (vpe_api_main_t * am,
+                           vl_api_registration_t * reg,
+                           u32 sw_if_index, u32 ip_sw_if_index, u32 context)
+{
+  vl_api_ip_unnumbered_details_t *mp;
+
+  mp = vl_msg_api_alloc (sizeof (*mp));
+  memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_IP_UNNUMBERED_DETAILS);
+
+  mp->context = context;
+  mp->sw_if_index = htonl (sw_if_index);
+  mp->ip_sw_if_index = htonl (ip_sw_if_index);
+
+  vl_api_send_msg (reg, (u8 *) mp);
+}
+
+static void
+vl_api_ip_unnumbered_dump_t_handler (vl_api_ip_unnumbered_dump_t * mp)
+{
+  vnet_main_t *vnm = vnet_get_main ();
+  vnet_interface_main_t *im = &vnm->interface_main;
+  int rv __attribute__ ((unused)) = 0;
+  vpe_api_main_t *am = &vpe_api_main;
+  vl_api_registration_t *reg;
+  vnet_sw_interface_t *si;
+  u32 sw_if_index;
+
+  sw_if_index = ntohl (mp->sw_if_index);
+
+  reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
+
+  if (~0 != sw_if_index)
+    {
+      VALIDATE_SW_IF_INDEX (mp);
+
+      si = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
+
+      if (!(si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
+       {
+         send_ip_unnumbered_details (am, reg,
+                                     sw_if_index,
+                                     si->unnumbered_sw_if_index,
+                                     mp->context);
+       }
+    }
+  else
+    {
+      /* *INDENT-OFF* */
+      pool_foreach (si, im->sw_interfaces,
+      ({
+        if ((si->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED))
+          {
+            send_ip_unnumbered_details(am, reg,
+                                       si->sw_if_index,
+                                       si->unnumbered_sw_if_index,
+                                       mp->context);
+          }
+      }));
+      /* *INDENT-ON* */
+    }
+
+  BAD_SW_IF_INDEX_LABEL;
+}
+
 static void
 vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp)
 {
@@ -1650,6 +1734,32 @@ vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp)
   REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY);
 }
 
+static void
+  vl_api_ip6nd_send_router_solicitation_t_handler
+  (vl_api_ip6nd_send_router_solicitation_t * mp)
+{
+  vl_api_ip6nd_send_router_solicitation_reply_t *rmp;
+  icmp6_send_router_solicitation_params_t params;
+  vlib_main_t *vm = vlib_get_main ();
+  int rv = 0;
+
+  VALIDATE_SW_IF_INDEX (mp);
+
+  BAD_SW_IF_INDEX_LABEL;
+  REPLY_MACRO (VL_API_IP6ND_SEND_ROUTER_SOLICITATION_REPLY);
+
+  if (rv != 0)
+    return;
+
+  params.irt = ntohl (mp->irt);
+  params.mrt = ntohl (mp->mrt);
+  params.mrc = ntohl (mp->mrc);
+  params.mrd = ntohl (mp->mrd);
+
+  icmp6_send_router_solicitation (vm, ntohl (mp->sw_if_index), mp->stop,
+                                 &params);
+}
+
 static void
   vl_api_sw_interface_ip6_enable_disable_t_handler
   (vl_api_sw_interface_ip6_enable_disable_t * mp)
@@ -2181,7 +2291,7 @@ nd_change_delete_callback (u32 pool_index, u8 * notused)
 static vlib_node_registration_t wc_arp_process_node;
 
 enum
-{ WC_ARP_REPORT, WC_ND_REPORT };
+{ WC_ARP_REPORT, WC_ND_REPORT, RA_REPORT, REPORT_MAX };
 
 static uword
 wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
@@ -2224,6 +2334,7 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
             ({
              vl_api_registration_t *vl_reg;
               vl_reg = vl_api_client_index_to_registration (reg->client_index);
+              ASSERT (vl_reg != NULL);
              if (reg && vl_api_can_send_msg (vl_reg))
                {
                  vl_api_ip4_arp_event_t * event = vl_msg_api_alloc (sizeof *event);
@@ -2280,6 +2391,78 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
             /* *INDENT-ON* */
            }
        }
+      else if (event_type == RA_REPORT)
+       {
+         ra_report_t *ra_events = event_data;
+         for (i = 0; i < vec_len (ra_events); i++)
+           {
+             ip6_neighbor_public_main_t *npm = &ip6_neighbor_public_main;
+             call_ip6_neighbor_callbacks (&ra_events[i],
+                                          npm->ra_report_functions);
+
+             vpe_client_registration_t *reg;
+              /* *INDENT-OFF* */
+              pool_foreach(reg, vpe_api_main.ip6_ra_events_registrations,
+              ({
+               vl_api_registration_t *vl_reg;
+               vl_reg =
+                 vl_api_client_index_to_registration (reg->client_index);
+               if (vl_reg && vl_api_can_send_msg (vl_reg))
+                 {
+                   u32 event_size =
+                     sizeof (vl_api_ip6_ra_event_t) +
+                     vec_len (ra_events[i].prefixes) *
+                     sizeof (vl_api_ip6_ra_prefix_info_t);
+                   vl_api_ip6_ra_event_t *event =
+                     vl_msg_api_alloc (event_size);
+                   memset (event, 0, event_size);
+                   event->_vl_msg_id = htons (VL_API_IP6_RA_EVENT);
+                   event->client_index = reg->client_index;
+                   event->pid = reg->client_pid;
+
+                   event->sw_if_index = clib_host_to_net_u32 (ra_events[i].sw_if_index);
+
+                   memcpy (event->router_address, ra_events[i].router_address, 16);
+
+                   event->current_hop_limit = ra_events[i].current_hop_limit;
+                   event->flags = ra_events[i].flags;
+                   event->router_lifetime_in_sec =
+                     clib_host_to_net_u16 (ra_events
+                                           [i].router_lifetime_in_sec);
+                   event->neighbor_reachable_time_in_msec =
+                     clib_host_to_net_u32 (ra_events
+                                           [i].neighbor_reachable_time_in_msec);
+                   event->time_in_msec_between_retransmitted_neighbor_solicitations
+                     =
+                     clib_host_to_net_u32 (ra_events
+                                           [i].time_in_msec_between_retransmitted_neighbor_solicitations);
+
+                   event->n_prefixes =
+                     clib_host_to_net_u32 (vec_len (ra_events[i].prefixes));
+                   vl_api_ip6_ra_prefix_info_t *prefix =
+                     (typeof (prefix)) event->prefixes;
+                   u32 j;
+                   for (j = 0; j < vec_len (ra_events[i].prefixes); j++)
+                     {
+                       ra_report_prefix_info_t *info =
+                         &ra_events[i].prefixes[j];
+                       memcpy (prefix->dst_address, info->dst_address.as_u8,
+                               16);
+                       prefix->dst_address_length = info->dst_address_length;
+                       prefix->flags = info->flags;
+                       prefix->valid_time =
+                         clib_host_to_net_u32 (info->valid_time);
+                       prefix->preferred_time =
+                         clib_host_to_net_u32 (info->preferred_time);
+                       prefix++;
+                     }
+
+                   vl_api_send_msg (vl_reg, (u8 *) event);
+                 }
+              }));
+            /* *INDENT-ON* */
+           }
+       }
       vlib_process_put_event_data (vm, event_data);
     }
 
@@ -2345,7 +2528,7 @@ vl_api_want_ip4_arp_events_t_handler (vl_api_want_ip4_arp_events_t * mp)
              hash_unset (am->wc_ip4_arp_events_registration_hash,
                          mp->client_index);
              if (pool_elts (am->wc_ip4_arp_events_registrations) == 0)
-               wc_arp_set_publisher_node (~0, WC_ARP_REPORT);
+               wc_arp_set_publisher_node (~0, REPORT_MAX);
              goto reply;
            }
        }
@@ -2430,7 +2613,7 @@ vl_api_want_ip6_nd_events_t_handler (vl_api_want_ip6_nd_events_t * mp)
              hash_unset (am->wc_ip6_nd_events_registration_hash,
                          mp->client_index);
              if (pool_elts (am->wc_ip6_nd_events_registrations) == 0)
-               wc_nd_set_publisher_node (~0, 2);
+               wc_nd_set_publisher_node (~0, REPORT_MAX);
              goto reply;
            }
        }
@@ -2484,6 +2667,47 @@ reply:
   REPLY_MACRO (VL_API_WANT_IP6_ND_EVENTS_REPLY);
 }
 
+static void
+vl_api_want_ip6_ra_events_t_handler (vl_api_want_ip6_ra_events_t * mp)
+{
+  vpe_api_main_t *am = &vpe_api_main;
+  vl_api_want_ip6_ra_events_reply_t *rmp;
+  int rv = 0;
+
+  uword *p = hash_get (am->ip6_ra_events_registration_hash, mp->client_index);
+  vpe_client_registration_t *rp;
+  if (p)
+    {
+      if (mp->enable_disable)
+       {
+         clib_warning ("pid %d: already enabled...", ntohl (mp->pid));
+         rv = VNET_API_ERROR_INVALID_REGISTRATION;
+         goto reply;
+       }
+      else
+       {
+         rp = pool_elt_at_index (am->ip6_ra_events_registrations, p[0]);
+         pool_put (am->ip6_ra_events_registrations, rp);
+         hash_unset (am->ip6_ra_events_registration_hash, mp->client_index);
+         goto reply;
+       }
+    }
+  if (mp->enable_disable == 0)
+    {
+      clib_warning ("pid %d: already disabled...", ntohl (mp->pid));
+      rv = VNET_API_ERROR_INVALID_REGISTRATION;
+      goto reply;
+    }
+  pool_get (am->ip6_ra_events_registrations, rp);
+  rp->client_index = mp->client_index;
+  rp->client_pid = ntohl (mp->pid);
+  hash_set (am->ip6_ra_events_registration_hash, rp->client_index,
+           rp - am->ip6_ra_events_registrations);
+
+reply:
+  REPLY_MACRO (VL_API_WANT_IP6_RA_EVENTS_REPLY);
+}
+
 static void
 vl_api_proxy_arp_add_del_t_handler (vl_api_proxy_arp_add_del_t * mp)
 {
@@ -2542,6 +2766,55 @@ static void
   REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
 }
 
+static void
+vl_api_ip_probe_neighbor_t_handler (vl_api_ip_probe_neighbor_t * mp)
+{
+  int rv = 0;
+  vlib_main_t *vm = vlib_get_main ();
+  vl_api_ip_probe_neighbor_reply_t *rmp;
+  clib_error_t *error;
+
+  VALIDATE_SW_IF_INDEX (mp);
+
+  u32 sw_if_index = ntohl (mp->sw_if_index);
+
+  if (mp->is_ipv6)
+    error = ip6_probe_neighbor (vm, (ip6_address_t *) mp->dst_address,
+                               sw_if_index);
+  else
+    error = ip4_probe_neighbor (vm, (ip4_address_t *) mp->dst_address,
+                               sw_if_index);
+
+  if (error)
+    {
+      clib_error_report (error);
+      rv = clib_error_get_code (error);
+    }
+
+  BAD_SW_IF_INDEX_LABEL;
+
+  REPLY_MACRO (VL_API_PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY);
+}
+
+static void
+  vl_api_ip_scan_neighbor_enable_disable_t_handler
+  (vl_api_ip_scan_neighbor_enable_disable_t * mp)
+{
+  int rv = 0;
+  vl_api_ip_scan_neighbor_enable_disable_reply_t *rmp;
+  ip_neighbor_scan_arg_t arg;
+
+  arg.mode = mp->mode;
+  arg.scan_interval = mp->scan_interval;
+  arg.max_proc_time = mp->max_proc_time;
+  arg.max_update = mp->max_update;
+  arg.scan_int_delay = mp->scan_int_delay;
+  arg.stale_threshold = mp->stale_threshold;
+  ip_neighbor_scan_enable_disable (&arg);
+
+  REPLY_MACRO (VL_API_IP_SCAN_NEIGHBOR_ENABLE_DISABLE_REPLY);
+}
+
 static int
 ip4_reset_fib_t_handler (vl_api_reset_fib_t * mp)
 {
@@ -2764,6 +3037,23 @@ vl_api_ip_reassembly_get_t_handler (vl_api_ip_reassembly_get_t * mp)
   vl_msg_api_send_shmem (q, (u8 *) & rmp);
 }
 
+void
+  vl_api_ip_reassembly_enable_disable_t_handler
+  (vl_api_ip_reassembly_enable_disable_t * mp)
+{
+  vl_api_ip_reassembly_enable_disable_reply_t *rmp;
+  int rv = 0;
+  rv = ip4_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
+                                mp->enable_ip4);
+  if (0 == rv)
+    {
+      rv = ip6_reass_enable_disable (clib_net_to_host_u32 (mp->sw_if_index),
+                                    mp->enable_ip6);
+    }
+
+  REPLY_MACRO (VL_API_IP_REASSEMBLY_SET_REPLY);
+}
+
 #define vl_msg_name_crc_list
 #include <vnet/ip/ip.api.h>
 #undef vl_msg_name_crc_list
@@ -2796,6 +3086,8 @@ ip_api_hookup (vlib_main_t * vm)
    */
   setup_message_id_table (am);
 
+  ra_set_publisher_node (wc_arp_process_node.index, RA_REPORT);
+
   return 0;
 }