/
* *INDENT-OFF* */ typedef CLIB_PACKED (struct { mac_address_t mac; ip4_address_t ip4; }) ethernet_arp_ip4_over_ethernet_address_t; /* *INDENT-ON* */ /* *INDENT-OFF* */ typedef CLIB_PACKED (struct { u8 mac[6]; ip4_address_t ip4; }) ethernet_arp_ip4_over_ethernet_address_t; /* *INDENT-ON* */
ip_neighbor_add
/** * @brief Control Plane hook to remove an ARP entry */ int vnet_arp_unset_ip4_over_ethernet (vnet_main_t * vnm, u32 sw_if_index, void *a_arg) { ethernet_arp_ip4_over_ethernet_address_t *a = a_arg; vnet_arp_set_ip4_over_ethernet_rpc_args_t args; args.sw_if_index = sw_if_index; args.flags = ETHERNET_ARP_ARGS_REMOVE; clib_memcpy (&args.a, a, sizeof (*a)); vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, (u8 *) & args, sizeof (args)); return 0; }
add_ip4_neighbor (test_main_t * tm, int add_del) { vl_api_ip_neighbor_add_del_t *mp; u32 tmp; mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_ADD_DEL); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; mp->sw_if_index = ntohl (6); mp->is_add = add_del; clib_memset (mp->mac_address, 0xbe, sizeof (mp->mac_address)); tmp = ntohl (0x0101010a); clib_memcpy (mp->dst_address, &tmp, 4); vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp); }
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_t_handler (vl_api_ip_neighbor_add_del_t * mp, vlib_main_t * vm) { if (mp->is_add) rv = vnet_arp_set_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a, mp->is_static, mp->is_no_adj_fib); else rv = vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a);
20.01 vl_api_ip_neighbor_add_del_t_handler if (mp->is_add) rv = ip_neighbor_add (&ip, type, &mac, ntohl (mp->neighbor.sw_if_index), flags, &stats_index); else rv = ip_neighbor_del (&ip, type, ntohl (mp->neighbor.sw_if_index));
ip_neighbor_learn (const ip_neighbor_learn_t * l) { ip_neighbor_add (&l->ip, l->type, &l->mac, l->sw_if_index, IP_NEIGHBOR_FLAG_DYNAMIC, NULL); }
flags = ip_neighbor_flags_decode (mp->neighbor.flags); type = ip_address_decode (&mp->neighbor.ip_address, &ip); mac_address_decode (mp->neighbor.mac_address, &mac); /* must be static or dynamic, default to dynamic */ if (!(flags & IP_NEIGHBOR_FLAG_STATIC) && !(flags & IP_NEIGHBOR_FLAG_DYNAMIC)) flags |= IP_NEIGHBOR_FLAG_DYNAMIC;
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; ip_neighbor_flags_t flags; u32 stats_index = ~0; ip46_address_t ip = ip46_address_initializer; mac_address_t mac; ip46_type_t type; int rv; VALIDATE_SW_IF_INDEX ((&mp->neighbor)); flags = ip_neighbor_flags_decode (mp->neighbor.flags); type = ip_address_decode (&mp->neighbor.ip_address, &ip); mac_address_decode (mp->neighbor.mac_address, &mac); /* must be static or dynamic, default to dynamic */ if (!(flags & IP_NEIGHBOR_FLAG_STATIC) && !(flags & IP_NEIGHBOR_FLAG_DYNAMIC)) flags |= IP_NEIGHBOR_FLAG_DYNAMIC; /* * there's no validation here of the ND/ARP entry being added. * The expectation is that the FIB will ensure that nothing bad * will come of adding bogus entries. */ if (mp->is_add) rv = ip_neighbor_add (&ip, type, &mac, ntohl (mp->neighbor.sw_if_index), flags, &stats_index); else rv = ip_neighbor_del (&ip, type, ntohl (mp->neighbor.sw_if_index)); BAD_SW_IF_INDEX_LABEL; /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY, ({ rmp->stats_index = htonl (stats_index); })); /* *INDENT-ON* */ }
void add_ip4_neighbor (test_main_t * tm, int add_del) { vl_api_ip_neighbor_add_del_t *mp; u32 tmp; mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_ADD_DEL); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; mp->sw_if_index = ntohl (6); mp->is_add = add_del; clib_memset (mp->mac_address, 0xbe, sizeof (mp->mac_address)); tmp = ntohl (0x0101010a); clib_memcpy (mp->dst_address, &tmp, 4); vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp); } void add_ip6_neighbor (test_main_t * tm, int add_del) { vl_api_ip_neighbor_add_del_t *mp; u64 tmp[2]; mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_ADD_DEL); mp->client_index = tm->my_client_index; mp->context = 0xdeadbeef; mp->sw_if_index = ntohl (6); mp->is_add = add_del; mp->is_ipv6 = 1; clib_memset (mp->mac_address, 0xbe, sizeof (mp->mac_address)); tmp[0] = clib_host_to_net_u64 (0xdb01000000000000ULL); tmp[1] = clib_host_to_net_u64 (0x11ULL); clib_memcpy (mp->dst_address, &tmp[0], 8); clib_memcpy (&mp->dst_address[8], &tmp[1], 8); vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp); }
typedef enum __attribute__((packed)) { IP_API_NEIGHBOR_FLAG_NONE = 0, IP_API_NEIGHBOR_FLAG_STATIC = 1, IP_API_NEIGHBOR_FLAG_NO_FIB_ENTRY = 2, } vl_api_ip_neighbor_flags_t; STATIC_ASSERT(sizeof(vl_api_ip_neighbor_flags_t) == sizeof(u8), "size of API enum ip_neighbor_flags is wrong"); typedef struct __attribute__ ((packed)) _vl_api_ip_neighbor { vl_api_interface_index_t sw_if_index; vl_api_ip_neighbor_flags_t flags; vl_api_mac_address_t mac_address; vl_api_address_t ip_address; } vl_api_ip_neighbor_t; typedef struct __attribute__ ((packed)) _vl_api_ip_neighbor_add_del { u16 _vl_msg_id; u32 client_index; u32 context; bool is_add; vl_api_ip_neighbor_t neighbor; } vl_api_ip_neighbor_add_del_t;
static void
ip_neighbor_encode (vl_api_ip_neighbor_t * api, const ip_neighbor_t * ipn)
{
api->sw_if_index = htonl (ipn->ipn_key->ipnk_sw_if_index);
api->flags = ip_neighbor_flags_encode (ipn->ipn_flags);
ip_address_encode (&ipn->ipn_key->ipnk_ip,
ipn->ipn_key->ipnk_type, &api->ip_address);
mac_address_encode (&ipn->ipn_mac, api->mac_address);
}
ip46_type_t ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) { return (ip_address_union_decode (&in->un, in->af, out)); } ip4_address_decode (const vl_api_ip4_address_t in, ip4_address_t * out) { clib_memcpy (out, in, sizeof (*out)); } void ip4_address_encode (const ip4_address_t * in, vl_api_ip4_address_t out) { clib_memcpy (out, in, sizeof (*in)); }
ip46_type_t
ip_address_decode (const vl_api_address_t * in, ip46_address_t * out)
{
return (ip_address_union_decode (&in->un, in->af, out));
}
ip_address_encode (const ip46_address_t * in,
ip46_type_t type, vl_api_address_t * out)
ip_neighbor_learn_dp (const ip_neighbor_learn_t * l) { vl_api_rpc_call_main_thread (ip_neighbor_learn, (u8 *) l, sizeof (*l)); }
int vnet_arp_set_ip4_over_ethernet (vnet_main_t * vnm, u32 sw_if_index, void *a_arg, int is_static, int is_no_fib_entry) { ethernet_arp_ip4_over_ethernet_address_t *a = a_arg; vnet_arp_set_ip4_over_ethernet_rpc_args_t args; args.sw_if_index = sw_if_index; args.is_static = is_static; args.is_no_fib_entry = is_no_fib_entry; args.flags = 0; clib_memcpy (&args.a, a, sizeof (*a)); vl_api_rpc_call_main_thread (set_ip4_over_ethernet_rpc_callback, (u8 *) & args, sizeof (args)); return 0; }
ip_neighbor_api_init (vlib_main_t * vm) { /* Ask for a correctly-sized block of API message decode slots */ msg_id_base = setup_message_id_table (); return 0; } /* *INDENT-OFF* */ typedef CLIB_PACKED (union ip46_address_t_ { struct { u32 pad[3]; ip4_address_t ip4; }; ip6_address_t ip6; u8 as_u8[16]; u64 as_u64[2]; }) ip46_address_t; /* *INDENT-ON* */ 20.01 always_inline u32 arp_learn (u32 sw_if_index, const ethernet_arp_ip4_over_ethernet_address_t * addr) { ip_neighbor_learn_t l = { .ip.ip4 = addr->ip4, .type = IP46_TYPE_IP4, .mac = addr->mac, .sw_if_index = sw_if_index, }; ip_neighbor_learn_dp (&l); return (ETHERNET_ARP_ERROR_l3_src_address_learned); }