/* *------------------------------------------------------------------ * ip_api.c - vnet ip api * * 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. *------------------------------------------------------------------ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define vl_typedefs /* define message structures */ #include #undef vl_typedefs #define vl_endianfun /* define message structures */ #include #undef vl_endianfun /* instantiate all the print functions we know about */ #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) #define vl_printfun #include #undef vl_printfun #include #define foreach_ip_api_msg \ _(IP_FIB_DUMP, ip_fib_dump) \ _(IP6_FIB_DUMP, ip6_fib_dump) \ _(IP_MFIB_DUMP, ip_mfib_dump) \ _(IP6_MFIB_DUMP, ip6_mfib_dump) \ _(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_DUMP, ip_dump) \ _(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \ _(IP_ADD_DEL_ROUTE, ip_add_del_route) \ _(IP_TABLE_ADD_DEL, ip_table_add_del) \ _(SET_IP_FLOW_HASH,set_ip_flow_hash) \ _(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) \ _(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \ _(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \ sw_interface_ip6_set_link_local_address) extern void stats_dslock_with_hint (int hint, int tag); extern void stats_dsunlock (void); static void send_ip_neighbor_details (u8 is_ipv6, u8 is_static, u8 * mac_address, u8 * ip_address, unix_shared_memory_queue_t * q, u32 context) { vl_api_ip_neighbor_details_t *mp; mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_NEIGHBOR_DETAILS); mp->context = context; mp->is_ipv6 = is_ipv6; mp->is_static = is_static; memcpy (mp->mac_address, mac_address, 6); memcpy (mp->ip_address, ip_address, (is_ipv6) ? 16 : 4); vl_msg_api_send_shmem (q, (u8 *) & mp); } static void vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) { unix_shared_memory_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; u32 sw_if_index = ntohl (mp->sw_if_index); if (mp->is_ipv6) { ip6_neighbor_t *n, *ns; ns = ip6_neighbors_entries (sw_if_index); /* *INDENT-OFF* */ vec_foreach (n, ns) { send_ip_neighbor_details (mp->is_ipv6, ((n->flags & IP6_NEIGHBOR_FLAG_STATIC) ? 1 : 0), (u8 *) n->link_layer_address, (u8 *) & (n->key.ip6_address.as_u8), q, mp->context); } /* *INDENT-ON* */ vec_free (ns); } else { ethernet_arp_ip4_entry_t *n, *ns; ns = ip4_neighbor_entries (sw_if_index); /* *INDENT-OFF* */ vec_foreach (n, ns) { send_ip_neighbor_details (mp->is_ipv6, ((n->flags & ETHERNET_ARP_IP4_ENTRY_FLAG_STATIC) ? 1 : 0), (u8*) n->ethernet_address, (u8*) & (n->ip4_address.as_u8), q, mp->context); } /* *INDENT-ON* */ vec_free (ns); } } void copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg) { int is_ip4; vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg; if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4) fp->afi = IP46_TYPE_IP4; else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6) fp->afi = IP46_TYPE_IP6; else { is_ip4 = ip46_address_is_ip4 (&api_rpath->rpath.frp_addr); if (is_ip4) fp->afi = IP46_TYPE_IP4; else fp->afi = IP46_TYPE_IP6; } if (fp->afi == IP46_TYPE_IP4) memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip4, sizeof (api_rpath->rpath.frp_addr.ip4)); else memcpy (fp->next_hop, &api_rpath->rpath.frp_addr.ip6, sizeof (api_rpath->rpath.frp_addr.ip6)); } static void send_ip_fib_details (vpe_api_main_t * am, unix_shared_memory_queue_t * q, const fib_table_t * table, const fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) { vl_api_ip_fib_details_t *mp; fib_route_path_encode_t *api_rpath; vl_api_fib_path_t *fp; int path_count; path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); mp->context = context; mp->table_id = htonl (table->ft_table_id); memcpy (mp->table_name, table->ft_desc, clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); mp->address_length = pfx->fp_len; memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4)); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); switch (api_rpath->dpo.dpoi_type) { case DPO_RECEIVE: fp->is_local = true; break; case DPO_DROP: fp->is_drop = true; break; case DPO_IP_NULL: switch (api_rpath->dpo.dpoi_index) { case IP_NULL_ACTION_NONE: fp->is_drop = true; break; case IP_NULL_ACTION_SEND_ICMP_UNREACH: fp->is_unreach = true; break; case IP_NULL_ACTION_SEND_ICMP_PROHIBIT: fp->is_prohibit = true; break; default: break; } break; default: break; } fp->weight = api_rpath->rpath.frp_weight; fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index); copy_fib_next_hop (api_rpath, fp); fp++; } vl_msg_api_send_shmem (q, (u8 *) & mp); } typedef struct vl_api_ip_fib_dump_walk_ctx_t_ { fib_node_index_t *feis; } vl_api_ip_fib_dump_walk_ctx_t; static int vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) { vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; vec_add1 (ctx->feis, fei); return (1); } static void vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; unix_shared_memory_queue_t *q; ip4_main_t *im = &ip4_main; fib_table_t *fib_table; fib_node_index_t *lfeip; fib_prefix_t pfx; u32 fib_index; fib_route_path_encode_t *api_rpaths; vl_api_ip_fib_dump_walk_ctx_t ctx = { .feis = NULL, }; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; /* *INDENT-OFF* */ pool_foreach (fib_table, im->fibs, ({ fib_table_walk(fib_table->ft_index, FIB_PROTOCOL_IP4, vl_api_ip_fib_dump_walk, &ctx); })); /* *INDENT-ON* */ vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort); vec_foreach (lfeip, ctx.feis) { fib_entry_get_prefix (*lfeip, &pfx); fib_index = fib_entry_get_fib_index (*lfeip); fib_table = fib_table_get (fib_index, pfx.fp_proto); api_rpaths = NULL; fib_entry_encode (*lfeip, &api_rpaths); send_ip_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context); vec_free (api_rpaths); } vec_free (ctx.feis); } static void send_ip6_fib_details (vpe_api_main_t * am, unix_shared_memory_queue_t * q, u32 table_id, fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) { vl_api_ip6_fib_details_t *mp; fib_route_path_encode_t *api_rpath; vl_api_fib_path_t *fp; int path_count; path_count = vec_len (api_rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS); mp->context = context; mp->table_id = htonl (table_id); mp->address_length = pfx->fp_len; memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); mp->count = htonl (path_count); fp = mp->path; vec_foreach (api_rpath, api_rpaths) { memset (fp, 0, sizeof (*fp)); switch (api_rpath->dpo.dpoi_type) { case DPO_RECEIVE: fp->is_local = true; break; case DPO_DROP: fp->is_drop = true; break; case DPO_IP_NULL: switch (api_rpath->dpo.dpoi_index) { case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_NONE: fp->is_drop = true; break; case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_UNREACH: fp->is_unreach = true; break; case IP_NULL_DPO_ACTION_NUM + IP_NULL_ACTION_SEND_ICMP_PROHIBIT: fp->is_prohibit = true; break; default: break; } break; default: break; } fp->weight = api_rpath->rpath.frp_weight; fp->preference = api_rpath->rpath.frp_preference; fp->sw_if_index = api_rpath->rpath.frp_sw_if_index; copy_fib_next_hop (api_rpath, fp); fp++; } vl_msg_api_send_shmem (q, (u8 *) & mp); } typedef struct apt_ip6_fib_show_ctx_t_ { u32 fib_index; fib_node_index_t *entries; } api_ip6_fib_show_ctx_t; static void api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg) { api_ip6_fib_show_ctx_t *ctx = arg; if ((kvp->key[2] >> 32) == ctx->fib_index) { vec_add1 (ctx->entries, kvp->value); } } static void api_ip6_fib_table_get_all (unix_shared_memory_queue_t * q, vl_api_ip6_fib_dump_t * mp, fib_table_t * fib_table) { vpe_api_main_t *am = &vpe_api_main; ip6_main_t *im6 = &ip6_main; fib_node_index_t *fib_entry_index; api_ip6_fib_show_ctx_t ctx = { .fib_index = fib_table->ft_index, .entries = NULL, }; fib_route_path_encode_t *api_rpaths; fib_prefix_t pfx; BV (clib_bihash_foreach_key_value_pair) ((BVT (clib_bihash) *) & im6->ip6_table[IP6_FIB_TABLE_NON_FWDING]. ip6_hash, api_ip6_fib_table_put_entries, &ctx); vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); vec_foreach (fib_entry_index, ctx.entries) { fib_entry_get_prefix (*fib_entry_index, &pfx); api_rpaths = NULL; fib_entry_encode (*fib_entry_index, &api_rpaths); send_ip6_fib_details (am, q, fib_table->ft_table_id, &pfx, api_rpaths, mp->context); vec_free (api_rpaths); } vec_free (ctx.entries); } static void vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) { unix_shared_memory_queue_t *q; ip6_main_t *im6 = &ip6_main; fib_table_t *fib_table; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; /* *INDENT-OFF* */ pool_foreach (fib_table, im6->fibs, ({ api_ip6_fib_table_get_all(q, mp, fib_table); })); /* *INDENT-ON* */ } static void send_ip_mfib_details (unix_shared_memory_queue_t * q,
/*
 * Copyright (c) 2015 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.
 */
/*
 * ip/ip_lookup.h: ip (4 or 6) lookup structures, adjacencies, ...
 *
 * Copyright (c) 2008 Eliot Dresselhaus
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @file
 * Definitions for all things IP (v4|v6) unicast and multicast lookup related.
 *
 * - Adjacency definitions and registration.
 * - Callbacks on route add.
 * - Callbacks on interface address change.
 */
#ifndef included_ip_lookup_h
#define included_ip_lookup_h

#include <vnet/vnet.h>
#include <vlib/buffer.h>
#include <vnet/ip/ip4_packet.h>
#include <vnet/ip/ip6_packet.h>
#include <vnet/fib/fib_node.h>
#include <vnet/adj/adj.h>
#include <vnet/dpo/dpo.h>
#include <vnet/feature/feature.h>

/** Flow hash configuration */
#define IP_FLOW_HASH_SRC_ADDR (1<<0)
#define IP_FLOW_HASH_DST_ADDR (1<<1)
#define IP_FLOW_HASH_PROTO (1<<2)
#define IP_FLOW_HASH_SRC_PORT (1<<3)
#define IP_FLOW_HASH_DST_PORT (1<<4)
#define IP_FLOW_HASH_REVERSE_SRC_DST (1<<5)

/** Default: 5-tuple without the "reverse" bit */
#define IP_FLOW_HASH_DEFAULT (0x1F)

#define foreach_flow_hash_bit                   \
_(src, IP_FLOW_HASH_SRC_ADDR)                   \
_(dst, IP_FLOW_HASH_DST_ADDR)                   \
_(sport, IP_FLOW_HASH_SRC_PORT)                 \
_(dport, IP_FLOW_HASH_DST_PORT)                 \
_(proto, IP_FLOW_HASH_PROTO)	                \
_(reverse, IP_FLOW_HASH_REVERSE_SRC_DST)

/**
 * A flow hash configuration is a mask of the flow hash options
 */
typedef u32 flow_hash_config_t;

/* An all zeros address */
extern const ip46_address_t zero_addr;


typedef struct
{
  /* Key for mhash; in fact, just a byte offset into mhash key vector. */
  u32 address_key;

  /* Interface which has this address. */
  u32 sw_if_index;

  /* Address (prefix) length for this interface. */
  u16 address_length;

  /* Will be used for something eventually.  Primary vs. secondary? */
  u16 flags;

  /* Next and previous pointers for doubly linked list of
     addresses per software interface. */
  u32 next_this_sw_interface;
  u32 prev_this_sw_interface;
} ip_interface_address_t;

typedef enum
{
  IP_LOCAL_NEXT_DROP,
  IP_LOCAL_NEXT_PUNT,
  IP_LOCAL_NEXT_UDP_LOOKUP,
  IP_LOCAL_NEXT_ICMP,
  IP_LOCAL_NEXT_REASSEMBLY,
  IP_LOCAL_N_NEXT,
} ip_local_next_t;

struct ip_lookup_main_t;

typedef struct ip_lookup_main_t
{
  /** Pool of addresses that are assigned to interfaces. */
  ip_interface_address_t *if_address_pool;

  /** Hash table mapping address to index in interface address pool. */
  mhash_t address_to_if_address_index;

  /** Head of doubly linked list of interface addresses for each software interface.
     ~0 means this interface has no address. */
  u32 *if_address_pool_index_by_sw_if_index;

  /** First table index to use for this interface, ~0 => none */
  u32 *classify_table_index_by_sw_if_index;

  /** Feature arc indices */
  u8 mcast_feature_arc_index;
  u8 ucast_feature_arc_index;
  u8 output_feature_arc_index;

  /** Number of bytes in a fib result.  Must be at least
     sizeof (uword).  First word is always adjacency index. */
  u32 fib_result_n_bytes, fib_result_n_words;

  /** 1 for ip6; 0 for ip4. */
  u32 is_ip6;

  /** Either format_ip4_address_and_length or format_ip6_address_and_length. */
  format_function_t *format_address_and_length;

  /** Table mapping ip protocol to ip[46]-local node next index. */
  u8 local_next_by_ip_protocol[256];

  /** IP_BUILTIN_PROTOCOL_{TCP,UDP,ICMP,OTHER} by protocol in IP header. */
  u8 builtin_protocol_by_ip_protocol[256];
} ip_lookup_main_t;

clib_error_t *ip_interface_address_add_del (ip_lookup_main_t * lm,
					    u32 sw_if_index,
					    void *address,
					    u32 address_length,
					    u32 is_del, u32 * result_index);

u8 *format_ip_flow_hash_config (u8 * s, va_list * args);

always_inline ip_interface_address_t *
ip_get_interface_address (ip_lookup_main_t * lm, void *addr_fib)
{
  uword *p = mhash_get (&lm->address_to_if_address_index, addr_fib);
  return p ? pool_elt_at_index (lm->if_address_pool, p[0]) : 0;
}

always_inline void *
ip_interface_address_get_address (ip_lookup_main_t * lm,
				  ip_interface_address_t * a)
{
  return mhash_key_to_mem (&lm->address_to_if_address_index, a->address_key);
}

/* *INDENT-OFF* */
#define foreach_ip_interface_address(lm,a,sw_if_index,loop,body)        \
do {                                                                    \
    vnet_main_t *_vnm = vnet_get_main();                                \
    u32 _sw_if_index = sw_if_index;                                     \
    vnet_sw_interface_t *_swif;                                         \
    _swif = vnet_get_sw_interface (_vnm, _sw_if_index);                 \
                                                                        \
    /*                                                                  \
     * Loop => honor unnumbered interface addressing.                   \
     */                                                                 \
    if (_swif->flags & VNET_SW_INTERFACE_FLAG_UNNUMBERED)               \
      {                                                                 \
        if (loop)                                                       \
          _sw_if_index = _swif->unnumbered_sw_if_index;                 \
        else                                                            \
          /* the interface is unnumbered, by the caller does not want   \
           * unnumbered interfaces considered/honoured */               \
          break;                                                        \
      }                                                                 \
    u32 _ia = ((vec_len((lm)->if_address_pool_index_by_sw_if_index)     \
                > (_sw_if_index)) ?                                     \
               vec_elt ((lm)->if_address_pool_index_by_sw_if_index,     \
                        (_sw_if_index)) :                               \
               (u32)~0);                                                \
    ip_interface_address_t * _a;                                        \
    while (_ia != ~0)                                                   \
    {                                                                   \
        _a = pool_elt_at_index ((lm)->if_address_pool, _ia);            \
        _ia = _a->next_this_sw_interface;                               \
        (a) = _a;                                                       \
        body;                                                           \
    }                                                                   \
} while (0)
/* *INDENT-ON* */

typedef struct _vnet_ip_container_proxy_args
{
  fib_prefix_t prefix;
  u32 sw_if_index;
  u8 is_add;
} vnet_ip_container_proxy_args_t;

clib_error_t *vnet_ip_container_proxy_add_del (vnet_ip_container_proxy_args_t
					       * args);

void ip_lookup_init (ip_lookup_main_t * lm, u32 ip_lookup_node_index);

#endif /* included_ip_lookup_h */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
dex); memcpy (mp->address, addr, 16); vl_msg_api_send_shmem (q, (u8 *) & mp); } typedef struct api_ip6nd_proxy_fib_table_walk_ctx_t_ { u32 *indices; } api_ip6nd_proxy_fib_table_walk_ctx_t; static int api_ip6nd_proxy_fib_table_walk (fib_node_index_t fei, void *arg) { api_ip6nd_proxy_fib_table_walk_ctx_t *ctx = arg; if (fib_entry_is_sourced (fei, FIB_SOURCE_IP6_ND_PROXY)) { vec_add1 (ctx->indices, fei); } return (1); } static void vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp) { ip6_main_t *im6 = &ip6_main; fib_table_t *fib_table; api_ip6nd_proxy_fib_table_walk_ctx_t ctx = { .indices = NULL, }; fib_node_index_t *feip; fib_prefix_t pfx; unix_shared_memory_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) { return; } /* *INDENT-OFF* */ pool_foreach (fib_table, im6->fibs, ({ fib_table_walk(fib_table->ft_index, FIB_PROTOCOL_IP6, api_ip6nd_proxy_fib_table_walk, &ctx); })); /* *INDENT-ON* */ vec_sort_with_function (ctx.indices, fib_entry_cmp_for_sort); vec_foreach (feip, ctx.indices) { fib_entry_get_prefix (*feip, &pfx); send_ip6nd_proxy_details (q, mp->context, &pfx.fp_addr, fib_entry_get_resolving_interface (*feip)); } vec_free (ctx.indices); } static void vl_api_ip6nd_proxy_add_del_t_handler (vl_api_ip6nd_proxy_add_del_t * mp) { vl_api_ip6nd_proxy_add_del_reply_t *rmp; int rv = 0; VALIDATE_SW_IF_INDEX (mp); rv = ip6_neighbor_proxy_add_del (ntohl (mp->sw_if_index), (ip6_address_t *) mp->address, mp->is_del); BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_IP6ND_PROXY_ADD_DEL_REPLY); } static void vl_api_sw_interface_ip6_enable_disable_t_handler (vl_api_sw_interface_ip6_enable_disable_t * mp) { vlib_main_t *vm = vlib_get_main (); vl_api_sw_interface_ip6_enable_disable_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); int rv = 0; clib_error_t *error; vnm->api_errno = 0; VALIDATE_SW_IF_INDEX (mp); error = (mp->enable == 1) ? enable_ip6_interface (vm, ntohl (mp->sw_if_index)) : disable_ip6_interface (vm, ntohl (mp->sw_if_index)); if (error) { clib_error_report (error); rv = VNET_API_ERROR_UNSPECIFIED; } else { rv = vnm->api_errno; } BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY); } static void vl_api_sw_interface_ip6_set_link_local_address_t_handler (vl_api_sw_interface_ip6_set_link_local_address_t * mp) { vlib_main_t *vm = vlib_get_main (); vl_api_sw_interface_ip6_set_link_local_address_reply_t *rmp; int rv = 0; clib_error_t *error; vnet_main_t *vnm = vnet_get_main (); vnm->api_errno = 0; VALIDATE_SW_IF_INDEX (mp); error = set_ip6_link_local_address (vm, ntohl (mp->sw_if_index), (ip6_address_t *) mp->address); if (error) { clib_error_report (error); rv = VNET_API_ERROR_UNSPECIFIED; } else { rv = vnm->api_errno; } BAD_SW_IF_INDEX_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY); } void vl_mfib_signal_send_one (unix_shared_memory_queue_t * q, u32 context, const mfib_signal_t * mfs) { vl_api_mfib_signal_details_t *mp; mfib_prefix_t prefix; mfib_table_t *mfib; mfib_itf_t *mfi; mp = vl_msg_api_alloc (sizeof (*mp)); memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_MFIB_SIGNAL_DETAILS); mp->context = context; mfi = mfib_itf_get (mfs->mfs_itf); mfib_entry_get_prefix (mfs->mfs_entry, &prefix); mfib = mfib_table_get (mfib_entry_get_fib_index (mfs->mfs_entry), prefix.fp_proto); mp->table_id = ntohl (mfib->mft_table_id); mp->sw_if_index = ntohl (mfi->mfi_sw_if_index); if (FIB_PROTOCOL_IP4 == prefix.fp_proto) { mp->grp_address_len = ntohs (prefix.fp_len); memcpy (mp->grp_address, &prefix.fp_grp_addr.ip4, 4); if (prefix.fp_len > 32) { memcpy (mp->src_address, &prefix.fp_src_addr.ip4, 4); } } else { mp->grp_address_len = ntohs (prefix.fp_len); ASSERT (0); } if (0 != mfs->mfs_buffer_len) { mp->ip_packet_len = ntohs (mfs->mfs_buffer_len); memcpy (mp->ip_packet_data, mfs->mfs_buffer, mfs->mfs_buffer_len); } else { mp->ip_packet_len = 0; } vl_msg_api_send_shmem (q, (u8 *) & mp); } static void vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp) { unix_shared_memory_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) { return; } while (q->cursize < q->maxsize && mfib_signal_send_one (q, mp->context)) ; } #define vl_msg_name_crc_list #include #undef vl_msg_name_crc_list static void setup_message_id_table (api_main_t * am) { #define _(id,n,crc) vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id); foreach_vl_msg_name_crc_ip; #undef _ } static clib_error_t * ip_api_hookup (vlib_main_t * vm) { api_main_t *am = &api_main; #define _(N,n) \ vl_msg_api_set_handlers(VL_API_##N, #n, \ vl_api_##n##_t_handler, \ vl_noop_handler, \ vl_api_##n##_t_endian, \ vl_api_##n##_t_print, \ sizeof(vl_api_##n##_t), 1); foreach_ip_api_msg; #undef _ /* * Set up the (msg_name, crc, message-id) table */ setup_message_id_table (am); return 0; } VLIB_API_INIT_FUNCTION (ip_api_hookup); /* * fd.io coding-style-patch-verification: ON * * Local Variables: * eval: (c-set-style "gnu") * End: */