#include <openssl/evp.h>
#include <openssl/hmac.h>
+u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
+
+typedef enum
+{
+ LISP_CP_INPUT_NEXT_DROP,
+ LISP_CP_INPUT_N_NEXT,
+} lisp_cp_input_next_t;
+
typedef struct
{
u8 is_resend;
pool_get (lcm->fwd_entry_pool, fe);
fe->locator_pairs = a->locator_pairs;
gid_address_copy (&fe->reid, &a->rmt_eid);
- gid_address_copy (&fe->leid, &src_map->eid);
+
+ if (is_src_dst)
+ gid_address_copy (&fe->leid, &a->lcl_eid);
+ else
+ gid_address_copy (&fe->leid, &src_map->eid);
+
fe->is_src_dst = is_src_dst;
hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
fe - lcm->fwd_entry_pool);
}
+typedef struct
+{
+ u32 si;
+ u32 di;
+} fwd_entry_mt_arg_t;
+
+static void *
+dp_add_fwd_entry_thread_fn (void *arg)
+{
+ fwd_entry_mt_arg_t *a = arg;
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ dp_add_fwd_entry (lcm, a->si, a->di);
+ return 0;
+}
+
+static int
+dp_add_fwd_entry_from_mt (u32 si, u32 di)
+{
+ fwd_entry_mt_arg_t a;
+
+ memset (&a, 0, sizeof (a));
+ a.si = si;
+ a.di = di;
+
+ vl_api_rpc_call_main_thread (dp_add_fwd_entry_thread_fn,
+ (u8 *) & a, sizeof (a));
+ return 0;
+}
+
/**
* Returns vector of adjacencies.
*
return 0;
}
+/* CP output statistics */
+#define foreach_lisp_cp_output_error \
+_(MAP_REGISTERS_SENT, "map-registers sent") \
+_(RLOC_PROBES_SENT, "rloc-probes sent")
+
+static char *lisp_cp_output_error_strings[] = {
+#define _(sym,string) string,
+ foreach_lisp_cp_output_error
+#undef _
+};
+
+typedef enum
+{
+#define _(sym,str) LISP_CP_OUTPUT_ERROR_##sym,
+ foreach_lisp_cp_output_error
+#undef _
+ LISP_CP_OUTPUT_N_ERROR,
+} lisp_cp_output_error_t;
+
+static uword
+lisp_cp_output (vlib_main_t * vm, vlib_node_runtime_t * node,
+ vlib_frame_t * from_frame)
+{
+ return 0;
+}
+
+/* dummy node used only for statistics */
+/* *INDENT-OFF* */
+VLIB_REGISTER_NODE (lisp_cp_output_node) = {
+ .function = lisp_cp_output,
+ .name = "lisp-cp-output",
+ .vector_size = sizeof (u32),
+ .format_trace = format_lisp_cp_input_trace,
+ .type = VLIB_NODE_TYPE_INTERNAL,
+
+ .n_errors = LISP_CP_OUTPUT_N_ERROR,
+ .error_strings = lisp_cp_output_error_strings,
+
+ .n_next_nodes = LISP_CP_INPUT_N_NEXT,
+
+ .next_nodes = {
+ [LISP_CP_INPUT_NEXT_DROP] = "error-drop",
+ },
+};
+/* *INDENT-ON* */
+
static int
send_rloc_probe (lisp_cp_main_t * lcm, gid_address_t * deid,
u32 local_locator_set_index, ip_address_t * sloc,
mapping_t *lm;
fwd_entry_t *e;
locator_pair_t *lp;
- u32 si;
+ u32 si, rloc_probes_sent = 0;
/* *INDENT-OFF* */
pool_foreach (e, lcm->fwd_entry_pool,
/* get first remote locator */
send_rloc_probe (lcm, &e->reid, lm->locator_set_index, &lp->lcl_loc,
&lp->rmt_loc);
+ rloc_probes_sent++;
}
});
/* *INDENT-ON* */
+ vlib_node_increment_counter (vlib_get_main (), lisp_cp_output_node.index,
+ LISP_CP_OUTPUT_ERROR_RLOC_PROBES_SENT,
+ rloc_probes_sent);
return 0;
}
static int
send_map_register (lisp_cp_main_t * lcm, u8 want_map_notif)
{
- u32 bi;
+ u32 bi, map_registers_sent = 0;
vlib_buffer_t *b;
ip_address_t sloc;
vlib_frame_t *f;
to_next[0] = bi;
f->n_vectors = 1;
vlib_put_frame_to_node (lcm->vlib_main, next_index, f);
+ map_registers_sent++;
hash_set (lcm->map_register_messages_by_nonce, nonce, 0);
}
free_map_register_records (records);
+ vlib_node_increment_counter (vlib_get_main (), lisp_cp_output_node.index,
+ LISP_CP_OUTPUT_ERROR_MAP_REGISTERS_SENT,
+ map_registers_sent);
+
return 0;
}
&src);
if (~0 != si)
{
- dp_add_fwd_entry (lcm, si, di);
+ dp_add_fwd_entry_from_mt (si, di);
}
}
}
/* *INDENT-ON* */
/* lisp_cp_input statistics */
-#define foreach_lisp_cp_input_error \
-_(DROP, "drop") \
+#define foreach_lisp_cp_input_error \
+_(DROP, "drop") \
+_(RLOC_PROBE_REQ_RECEIVED, "rloc-probe requests received") \
+_(RLOC_PROBE_REP_RECEIVED, "rloc-probe replies received") \
+_(MAP_NOTIFIES_RECEIVED, "map-notifies received") \
_(MAP_REPLIES_RECEIVED, "map-replies received")
static char *lisp_cp_input_error_strings[] = {
LISP_CP_INPUT_N_ERROR,
} lisp_cp_input_error_t;
-typedef enum
-{
- LISP_CP_INPUT_NEXT_DROP,
- LISP_CP_INPUT_N_NEXT,
-} lisp_cp_input_next_t;
-
typedef struct
{
gid_address_t dst_eid;
return 0;
}
+static void
+find_ip_header (vlib_buffer_t * b, u8 ** ip_hdr)
+{
+ const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+ if (start < 0 && start < -sizeof (b->pre_data))
+ {
+ *ip_hdr = 0;
+ return;
+ }
+
+ *ip_hdr = b->data + start;
+ if ((u8 *) * ip_hdr > (u8 *) vlib_buffer_get_current (b))
+ *ip_hdr = 0;
+}
+
void
-process_map_request (vlib_main_t * vm, lisp_cp_main_t * lcm,
- vlib_buffer_t * b)
+process_map_request (vlib_main_t * vm, vlib_node_runtime_t * node,
+ lisp_cp_main_t * lcm, vlib_buffer_t * b)
{
- u8 *ip_hdr = 0, *udp_hdr;
- ip4_header_t *ip4;
- ip6_header_t *ip6;
+ u8 *ip_hdr = 0;
ip_address_t *dst_loc = 0, probed_loc, src_loc;
mapping_t m;
map_request_hdr_t *mreq_hdr;
gid_address_t src, dst;
u64 nonce;
- u32 i, len = 0;
+ u32 i, len = 0, rloc_probe_recv = 0;
gid_address_t *itr_rlocs = 0;
mreq_hdr = vlib_buffer_get_current (b);
-
- // TODO ugly workaround to find out whether LISP is carried by ip4 or 6
- // and needs to be fixed
- udp_hdr = (u8 *) vlib_buffer_get_current (b) - sizeof (udp_header_t);
- ip4 = (ip4_header_t *) (udp_hdr - sizeof (ip4_header_t));
- ip6 = (ip6_header_t *) (udp_hdr - sizeof (ip6_header_t));
-
- if ((ip4->ip_version_and_header_length & 0xF0) == 0x40)
- ip_hdr = (u8 *) ip4;
- else
- {
- u32 flags = clib_net_to_host_u32
- (ip6->ip_version_traffic_class_and_flow_label);
- if ((flags & 0xF0000000) == 0x60000000)
- ip_hdr = (u8 *) ip6;
- else
- {
- clib_warning ("internal error: cannot determine whether packet "
- "is ip4 or 6!");
- return;
- }
- }
-
- vlib_buffer_pull (b, sizeof (*mreq_hdr));
-
- nonce = MREQ_NONCE (mreq_hdr);
-
if (!MREQ_SMR (mreq_hdr) && !MREQ_RLOC_PROBE (mreq_hdr))
{
clib_warning
return;
}
+ vlib_buffer_pull (b, sizeof (*mreq_hdr));
+ nonce = MREQ_NONCE (mreq_hdr);
+
/* parse src eid */
len = lisp_msg_parse_addr (b, &src);
if (len == ~0)
len = lisp_msg_parse_itr_rlocs (b, &itr_rlocs,
MREQ_ITR_RLOC_COUNT (mreq_hdr) + 1);
if (len == ~0)
- return;
+ goto done;
/* parse eid records and send SMR-invoked map-requests */
for (i = 0; i < MREQ_REC_COUNT (mreq_hdr); i++)
}
else if (MREQ_RLOC_PROBE (mreq_hdr))
{
+ find_ip_header (b, &ip_hdr);
+ if (!ip_hdr)
+ {
+ clib_warning ("Cannot find the IP header!");
+ goto done;
+ }
+ rloc_probe_recv++;
memset (&m, 0, sizeof (m));
u32 mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
}
done:
+ vlib_node_increment_counter (vm, node->node_index,
+ LISP_CP_INPUT_ERROR_RLOC_PROBE_REQ_RECEIVED,
+ rloc_probe_recv);
vec_free (itr_rlocs);
}
static void
queue_map_reply_for_processing (map_records_arg_t * a)
{
- vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (a));
+ vl_api_rpc_call_main_thread (process_map_reply, (u8 *) a, sizeof (*a));
}
static void
lisp_cp_input (vlib_main_t * vm, vlib_node_runtime_t * node,
vlib_frame_t * from_frame)
{
- u32 n_left_from, *from, *to_next_drop;
+ u32 n_left_from, *from, *to_next_drop, rloc_probe_rep_recv = 0,
+ map_notifies_recv = 0;
lisp_msg_type_e type;
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
map_records_arg_t *a;
case LISP_MAP_REPLY:
a = parse_map_reply (b0);
if (a)
- queue_map_reply_for_processing (a);
+ {
+ if (a->is_rloc_probe)
+ rloc_probe_rep_recv++;
+ queue_map_reply_for_processing (a);
+ }
break;
case LISP_MAP_REQUEST:
- process_map_request (vm, lcm, b0);
+ process_map_request (vm, node, lcm, b0);
break;
case LISP_MAP_NOTIFY:
a = parse_map_notify (b0);
if (a)
- queue_map_notify_for_processing (a);
+ {
+ map_notifies_recv++;
+ queue_map_notify_for_processing (a);
+ }
break;
default:
clib_warning ("Unsupported LISP message type %d", type);
vlib_put_next_frame (vm, node, LISP_CP_INPUT_NEXT_DROP,
n_left_to_next_drop);
}
+ vlib_node_increment_counter (vm, node->node_index,
+ LISP_CP_INPUT_ERROR_RLOC_PROBE_REP_RECEIVED,
+ rloc_probe_rep_recv);
+ vlib_node_increment_counter (vm, node->node_index,
+ LISP_CP_INPUT_ERROR_MAP_NOTIFIES_RECEIVED,
+ map_notifies_recv);
return from_frame->n_vectors;
}