summaryrefslogtreecommitdiffstats
path: root/vpp-api-test
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2016-10-26 14:31:24 +0200
committerFlorin Coras <florin.coras@gmail.com>2016-12-06 09:30:43 +0000
commit397fd7d39f023887e428de37a1929c366a99b8d5 (patch)
tree3a90215e1eab0fab2f3c6765c471591d64852b08 /vpp-api-test
parentb09167f33d3c79e7ccc27e0fc484cc5fbcdb9943 (diff)
Implement LISP control plane messages
* Map-register * Map-notify * RLOC probing Change-Id: I7f6295376b21cd67805446dfd1c1033acead2d4b Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'vpp-api-test')
-rw-r--r--vpp-api-test/vat/api_format.c413
1 files changed, 408 insertions, 5 deletions
diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c
index 63928063137..003fd723714 100644
--- a/vpp-api-test/vat/api_format.c
+++ b/vpp-api-test/vat/api_format.c
@@ -2337,11 +2337,13 @@ vl_api_lisp_eid_table_details_t_handler (vl_api_lisp_eid_table_details_t * mp)
mp->seid, mp->seid_prefix_len, mp->is_src_dst);
vec_add1 (eid, 0);
- fformat (vam->ofp, "[%d] %-35s%-20s%-30s%-20d%-d\n",
+ fformat (vam->ofp, "[%d] %-35s%-20s%-30s%-20d%-20d%-10d%-20s\n",
clib_net_to_host_u32 (mp->vni),
eid,
mp->is_local ? "local" : "remote",
- s, clib_net_to_host_u32 (mp->ttl), mp->authoritative);
+ s, clib_net_to_host_u32 (mp->ttl), mp->authoritative,
+ clib_net_to_host_u16 (mp->key_id), mp->key);
+
vec_free (s);
vec_free (eid);
}
@@ -2379,6 +2381,13 @@ vl_api_lisp_eid_table_details_t_handler_json (vl_api_lisp_eid_table_details_t
vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni));
vat_json_object_add_uint (node, "ttl", clib_net_to_host_u32 (mp->ttl));
vat_json_object_add_uint (node, "authoritative", (mp->authoritative));
+
+ if (mp->key_id)
+ {
+ vat_json_object_add_uint (node, "key_id",
+ clib_net_to_host_u16 (mp->key_id));
+ vat_json_object_add_string_copy (node, "key", mp->key);
+ }
vec_free (eid);
}
@@ -2540,6 +2549,76 @@ static void
}
static void
+ vl_api_show_lisp_map_register_state_reply_t_handler
+ (vl_api_show_lisp_map_register_state_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ fformat (vam->ofp, "%s\n", mp->is_enabled ? "enabled" : "disabled");
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+ vl_api_show_lisp_map_register_state_reply_t_handler_json
+ (vl_api_show_lisp_map_register_state_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t _node, *node = &_node;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ u8 *s = format (0, "%s", mp->is_enabled ? "enabled" : "disabled");
+
+ vat_json_init_object (node);
+ vat_json_object_add_string_copy (node, "state", s);
+
+ vat_json_print (vam->ofp, node);
+ vat_json_free (node);
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+ vec_free (s);
+}
+
+static void
+ vl_api_show_lisp_rloc_probe_state_reply_t_handler
+ (vl_api_show_lisp_rloc_probe_state_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ if (retval)
+ goto end;
+
+ fformat (vam->ofp, "%s\n", mp->is_enabled ? "enabled" : "disabled");
+end:
+ vam->retval = retval;
+ vam->result_ready = 1;
+}
+
+static void
+ vl_api_show_lisp_rloc_probe_state_reply_t_handler_json
+ (vl_api_show_lisp_rloc_probe_state_reply_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t _node, *node = &_node;
+ int retval = clib_net_to_host_u32 (mp->retval);
+
+ u8 *s = format (0, "%s", mp->is_enabled ? "enabled" : "disabled");
+ vat_json_init_object (node);
+ vat_json_object_add_string_copy (node, "state", s);
+
+ vat_json_print (vam->ofp, node);
+ vat_json_free (node);
+
+ vam->retval = retval;
+ vam->result_ready = 1;
+ vec_free (s);
+}
+
+static void
vl_api_lisp_adjacencies_get_reply_t_handler
(vl_api_lisp_adjacencies_get_reply_t * mp)
{
@@ -2612,6 +2691,46 @@ end:
}
static void
+vl_api_lisp_map_server_details_t_handler (vl_api_lisp_map_server_details_t
+ * mp)
+{
+ vat_main_t *vam = &vat_main;
+
+ fformat (vam->ofp, "%=20U\n",
+ mp->is_ipv6 ? format_ip6_address : format_ip4_address,
+ mp->ip_address);
+}
+
+static void
+ vl_api_lisp_map_server_details_t_handler_json
+ (vl_api_lisp_map_server_details_t * mp)
+{
+ vat_main_t *vam = &vat_main;
+ vat_json_node_t *node = NULL;
+ struct in6_addr ip6;
+ struct in_addr ip4;
+
+ if (VAT_JSON_ARRAY != vam->json_tree.type)
+ {
+ ASSERT (VAT_JSON_NONE == vam->json_tree.type);
+ vat_json_init_array (&vam->json_tree);
+ }
+ node = vat_json_array_add (&vam->json_tree);
+
+ vat_json_init_object (node);
+ if (mp->is_ipv6)
+ {
+ clib_memcpy (&ip6, mp->ip_address, sizeof (ip6));
+ vat_json_object_add_ip6 (node, "map-server", ip6);
+ }
+ else
+ {
+ clib_memcpy (&ip4, mp->ip_address, sizeof (ip4));
+ vat_json_object_add_ip4 (node, "map-server", ip4);
+ }
+}
+
+static void
vl_api_lisp_map_resolver_details_t_handler (vl_api_lisp_map_resolver_details_t
* mp)
{
@@ -3521,9 +3640,12 @@ _(lisp_add_del_remote_mapping_reply) \
_(lisp_add_del_adjacency_reply) \
_(lisp_gpe_add_del_fwd_entry_reply) \
_(lisp_add_del_map_resolver_reply) \
+_(lisp_add_del_map_server_reply) \
_(lisp_gpe_enable_disable_reply) \
_(lisp_gpe_add_del_iface_reply) \
_(lisp_enable_disable_reply) \
+_(lisp_rloc_probe_enable_disable_reply) \
+_(lisp_map_register_enable_disable_reply) \
_(lisp_pitr_set_locator_set_reply) \
_(lisp_map_request_mode_reply) \
_(lisp_add_del_map_request_itr_rlocs_reply) \
@@ -3726,8 +3848,13 @@ _(LISP_ADD_DEL_REMOTE_MAPPING_REPLY, lisp_add_del_remote_mapping_reply) \
_(LISP_ADD_DEL_ADJACENCY_REPLY, lisp_add_del_adjacency_reply) \
_(LISP_GPE_ADD_DEL_FWD_ENTRY_REPLY, lisp_gpe_add_del_fwd_entry_reply) \
_(LISP_ADD_DEL_MAP_RESOLVER_REPLY, lisp_add_del_map_resolver_reply) \
+_(LISP_ADD_DEL_MAP_SERVER_REPLY, lisp_add_del_map_server_reply) \
_(LISP_GPE_ENABLE_DISABLE_REPLY, lisp_gpe_enable_disable_reply) \
_(LISP_ENABLE_DISABLE_REPLY, lisp_enable_disable_reply) \
+_(LISP_MAP_REGISTER_ENABLE_DISABLE_REPLY, \
+ lisp_map_register_enable_disable_reply) \
+_(LISP_RLOC_PROBE_ENABLE_DISABLE_REPLY, \
+ lisp_rloc_probe_enable_disable_reply) \
_(LISP_PITR_SET_LOCATOR_SET_REPLY, lisp_pitr_set_locator_set_reply) \
_(LISP_MAP_REQUEST_MODE_REPLY, lisp_map_request_mode_reply) \
_(LISP_EID_TABLE_ADD_DEL_MAP_REPLY, lisp_eid_table_add_del_map_reply) \
@@ -3739,6 +3866,7 @@ _(LISP_EID_TABLE_MAP_DETAILS, lisp_eid_table_map_details) \
_(LISP_EID_TABLE_VNI_DETAILS, lisp_eid_table_vni_details) \
_(LISP_GPE_TUNNEL_DETAILS, lisp_gpe_tunnel_details) \
_(LISP_MAP_RESOLVER_DETAILS, lisp_map_resolver_details) \
+_(LISP_MAP_SERVER_DETAILS, lisp_map_server_details) \
_(LISP_ADJACENCIES_GET_REPLY, lisp_adjacencies_get_reply) \
_(SHOW_LISP_STATUS_REPLY, show_lisp_status_reply) \
_(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY, \
@@ -3747,6 +3875,9 @@ _(LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY, \
lisp_get_map_request_itr_rlocs_reply) \
_(SHOW_LISP_PITR_REPLY, show_lisp_pitr_reply) \
_(SHOW_LISP_MAP_REQUEST_MODE_REPLY, show_lisp_map_request_mode_reply) \
+_(SHOW_LISP_RLOC_PROBE_STATE_REPLY, show_lisp_rloc_probe_state_reply) \
+_(SHOW_LISP_MAP_REGISTER_STATE_REPLY, \
+ show_lisp_map_register_state_reply) \
_(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \
_(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \
_(POLICER_ADD_DEL_REPLY, policer_add_del_reply) \
@@ -12849,6 +12980,31 @@ api_lisp_add_del_locator (vat_main_t * vam)
return 0;
}
+uword
+unformat_hmac_key_id (unformat_input_t * input, va_list * args)
+{
+ u32 *key_id = va_arg (*args, u32 *);
+ u8 *s = 0;
+
+ if (unformat (input, "%s", &s))
+ {
+ if (!strcmp ((char *) s, "sha1"))
+ key_id[0] = HMAC_SHA_1_96;
+ else if (!strcmp ((char *) s, "sha256"))
+ key_id[0] = HMAC_SHA_256_128;
+ else
+ {
+ clib_warning ("invalid key_id: '%s'", s);
+ key_id[0] = HMAC_NO_KEY;
+ }
+ }
+ else
+ return 0;
+
+ vec_free (s);
+ return 1;
+}
+
static int
api_lisp_add_del_local_eid (vat_main_t * vam)
{
@@ -12861,6 +13017,8 @@ api_lisp_add_del_local_eid (vat_main_t * vam)
u8 *locator_set_name = 0;
u8 locator_set_name_set = 0;
u32 vni = 0;
+ u16 key_id = 0;
+ u8 *key = 0;
/* Parse args required to build the message */
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
@@ -12881,6 +13039,10 @@ api_lisp_add_del_local_eid (vat_main_t * vam)
{
locator_set_name_set = 1;
}
+ else if (unformat (input, "key-id %U", unformat_hmac_key_id, &key_id))
+ ;
+ else if (unformat (input, "secret-key %_%v%_", &key))
+ ;
else
break;
}
@@ -12898,6 +13060,19 @@ api_lisp_add_del_local_eid (vat_main_t * vam)
return -99;
}
+ if (key && (0 == key_id))
+ {
+ errmsg ("invalid key_id!");
+ return -99;
+ }
+
+ if (vec_len (key) > 64)
+ {
+ errmsg ("key too long");
+ vec_free (key);
+ return -99;
+ }
+
if (vec_len (locator_set_name) > 64)
{
errmsg ("locator-set name too long\n");
@@ -12914,10 +13089,13 @@ api_lisp_add_del_local_eid (vat_main_t * vam)
mp->eid_type = eid->type;
mp->prefix_len = eid->len;
mp->vni = clib_host_to_net_u32 (vni);
+ mp->key_id = clib_host_to_net_u16 (key_id);
clib_memcpy (mp->locator_set_name, locator_set_name,
vec_len (locator_set_name));
+ clib_memcpy (mp->key, key, vec_len (key));
vec_free (locator_set_name);
+ vec_free (key);
/* send it... */
S;
@@ -13071,6 +13249,74 @@ api_lisp_gpe_add_del_fwd_entry (vat_main_t * vam)
}
static int
+api_lisp_add_del_map_server (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_lisp_add_del_map_server_t *mp;
+ f64 timeout = ~0;
+ u8 is_add = 1;
+ u8 ipv4_set = 0;
+ u8 ipv6_set = 0;
+ ip4_address_t ipv4;
+ ip6_address_t ipv6;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "del"))
+ {
+ is_add = 0;
+ }
+ else if (unformat (input, "%U", unformat_ip4_address, &ipv4))
+ {
+ ipv4_set = 1;
+ }
+ else if (unformat (input, "%U", unformat_ip6_address, &ipv6))
+ {
+ ipv6_set = 1;
+ }
+ else
+ break;
+ }
+
+ if (ipv4_set && ipv6_set)
+ {
+ errmsg ("both eid v4 and v6 addresses set\n");
+ return -99;
+ }
+
+ if (!ipv4_set && !ipv6_set)
+ {
+ errmsg ("eid addresses not set\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (LISP_ADD_DEL_MAP_SERVER, lisp_add_del_map_server);
+
+ mp->is_add = is_add;
+ if (ipv6_set)
+ {
+ mp->is_ipv6 = 1;
+ clib_memcpy (mp->ip_address, &ipv6, sizeof (ipv6));
+ }
+ else
+ {
+ mp->is_ipv6 = 0;
+ clib_memcpy (mp->ip_address, &ipv4, sizeof (ipv4));
+ }
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
api_lisp_add_del_map_resolver (vat_main_t * vam)
{
unformat_input_t *input = vam->input;
@@ -13186,6 +13432,94 @@ api_lisp_gpe_enable_disable (vat_main_t * vam)
}
static int
+api_lisp_rloc_probe_enable_disable (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_lisp_rloc_probe_enable_disable_t *mp;
+ f64 timeout = ~0;
+ u8 is_set = 0;
+ u8 is_en = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "enable"))
+ {
+ is_set = 1;
+ is_en = 1;
+ }
+ else if (unformat (input, "disable"))
+ is_set = 1;
+ else
+ break;
+ }
+
+ if (!is_set)
+ {
+ errmsg ("Value not set\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (LISP_RLOC_PROBE_ENABLE_DISABLE, lisp_rloc_probe_enable_disable);
+
+ mp->is_enabled = is_en;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
+api_lisp_map_register_enable_disable (vat_main_t * vam)
+{
+ unformat_input_t *input = vam->input;
+ vl_api_lisp_map_register_enable_disable_t *mp;
+ f64 timeout = ~0;
+ u8 is_set = 0;
+ u8 is_en = 0;
+
+ /* Parse args required to build the message */
+ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (input, "enable"))
+ {
+ is_set = 1;
+ is_en = 1;
+ }
+ else if (unformat (input, "disable"))
+ is_set = 1;
+ else
+ break;
+ }
+
+ if (!is_set)
+ {
+ errmsg ("Value not set\n");
+ return -99;
+ }
+
+ /* Construct the API message */
+ M (LISP_MAP_REGISTER_ENABLE_DISABLE, lisp_map_register_enable_disable);
+
+ mp->is_enabled = is_en;
+
+ /* send it... */
+ S;
+
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
api_lisp_enable_disable (vat_main_t * vam)
{
unformat_input_t *input = vam->input;
@@ -13232,6 +13566,40 @@ api_lisp_enable_disable (vat_main_t * vam)
}
static int
+api_show_lisp_map_register_state (vat_main_t * vam)
+{
+ f64 timeout = ~0;
+ vl_api_show_lisp_map_register_state_t *mp;
+
+ M (SHOW_LISP_MAP_REGISTER_STATE, show_lisp_map_register_state);
+
+ /* send */
+ S;
+
+ /* wait for reply */
+ W;
+
+ return 0;
+}
+
+static int
+api_show_lisp_rloc_probe_state (vat_main_t * vam)
+{
+ f64 timeout = ~0;
+ vl_api_show_lisp_rloc_probe_state_t *mp;
+
+ M (SHOW_LISP_RLOC_PROBE_STATE, show_lisp_rloc_probe_state);
+
+ /* send */
+ S;
+
+ /* wait for reply */
+ W;
+
+ return 0;
+}
+
+static int
api_show_lisp_map_request_mode (vat_main_t * vam)
{
f64 timeout = ~0;
@@ -14107,8 +14475,8 @@ api_lisp_eid_table_dump (vat_main_t * vam)
if (!vam->json_output)
{
- fformat (vam->ofp, "%-35s%-20s%-30s%-20s%-s\n", "EID", "type",
- "ls_index", "ttl", "authoritative");
+ fformat (vam->ofp, "%-35s%-20s%-30s%-20s%-20s%-10s%-20s\n", "EID",
+ "type", "ls_index", "ttl", "authoritative", "key_id", "key");
}
M (LISP_EID_TABLE_DUMP, lisp_eid_table_dump);
@@ -14234,6 +14602,34 @@ api_lisp_adjacencies_get (vat_main_t * vam)
}
static int
+api_lisp_map_server_dump (vat_main_t * vam)
+{
+ vl_api_lisp_map_server_dump_t *mp;
+ f64 timeout = ~0;
+
+ if (!vam->json_output)
+ {
+ fformat (vam->ofp, "%=20s\n", "Map server");
+ }
+
+ M (LISP_MAP_SERVER_DUMP, lisp_map_server_dump);
+ /* send it... */
+ S;
+
+ /* Use a control ping for synchronization */
+ {
+ vl_api_control_ping_t *mp;
+ M (CONTROL_PING, control_ping);
+ S;
+ }
+ /* Wait for a reply... */
+ W;
+
+ /* NOTREACHED */
+ return 0;
+}
+
+static int
api_lisp_map_resolver_dump (vat_main_t * vam)
{
vl_api_lisp_map_resolver_dump_t *mp;
@@ -16991,12 +17387,16 @@ _(lisp_add_del_locator, "locator-set <locator_name> " \
"p <priority> w <weight> [del]") \
_(lisp_add_del_local_eid,"vni <vni> eid " \
"<ipv4|ipv6>/<prefix> | <L2 address> " \
- "locator-set <locator_name> [del]") \
+ "locator-set <locator_name> [del]" \
+ "[key-id sha1|sha256 secret-key <secret-key>]")\
_(lisp_gpe_add_del_fwd_entry, "rmt_eid <eid> [lcl_eid <eid>] vni <vni>" \
"dp_table <table> loc-pair <lcl_loc> <rmt_loc> ... [del]") \
_(lisp_add_del_map_resolver, "<ip4|6-addr> [del]") \
+_(lisp_add_del_map_server, "<ip4|6-addr> [del]") \
_(lisp_gpe_enable_disable, "enable|disable") \
_(lisp_enable_disable, "enable|disable") \
+_(lisp_map_register_enable_disable, "enable|disable") \
+_(lisp_rloc_probe_enable_disable, "enable|disable") \
_(lisp_gpe_add_del_iface, "up|down") \
_(lisp_add_del_remote_mapping, "add|del vni <vni> eid <dest-eid> " \
"[seid <seid>] " \
@@ -17017,7 +17417,10 @@ _(lisp_eid_table_vni_dump, "") \
_(lisp_eid_table_map_dump, "l2|l3") \
_(lisp_gpe_tunnel_dump, "") \
_(lisp_map_resolver_dump, "") \
+_(lisp_map_server_dump, "") \
_(lisp_adjacencies_get, "vni <vni>") \
+_(show_lisp_rloc_probe_state, "") \
+_(show_lisp_map_register_state, "") \
_(show_lisp_status, "") \
_(lisp_get_map_request_itr_rlocs, "") \
_(show_lisp_pitr, "") \
lass="o">* t1 = NULL; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; next_index = node->cached_next_index; stats_sw_if_index = node->runtime_data[0]; stats_n_packets = stats_n_bytes = 0; while (n_left_from > 0) { u32 n_left_to_next; vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); while (n_left_from >= 4 && n_left_to_next >= 2) { u32 bi0, bi1; vlib_buffer_t * b0, * b1; u32 flow_hash0, flow_hash1; u32 len0, len1; ip4_header_t * ip4_0, * ip4_1; ip6_header_t * ip6_0, * ip6_1; udp_header_t * udp0, * udp1; u64 * copy_src0, * copy_dst0; u64 * copy_src1, * copy_dst1; u32 * copy_src_last0, * copy_dst_last0; u32 * copy_src_last1, * copy_dst_last1; u16 new_l0, new_l1; ip_csum_t sum0, sum1; /* Prefetch next iteration. */ { vlib_buffer_t * p2, * p3; p2 = vlib_get_buffer (vm, from[2]); p3 = vlib_get_buffer (vm, from[3]); vlib_prefetch_buffer_header (p2, LOAD); vlib_prefetch_buffer_header (p3, LOAD); CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD); } bi0 = from[0]; bi1 = from[1]; to_next[0] = bi0; to_next[1] = bi1; from += 2; to_next += 2; n_left_to_next -= 2; n_left_from -= 2; b0 = vlib_get_buffer (vm, bi0); b1 = vlib_get_buffer (vm, bi1); flow_hash0 = vnet_l2_compute_flow_hash (b0); flow_hash1 = vnet_l2_compute_flow_hash (b1); /* Get next node index and adj index from tunnel next_dpo */ if (sw_if_index0 != vnet_buffer(b0)->sw_if_index[VLIB_TX]) { sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_TX]; hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); t0 = &vxm->tunnels[hi0->dev_instance]; /* Note: change to always set next0 if it may be set to drop */ next0 = t0->next_dpo.dpoi_next_node; } vnet_buffer(b0)->ip.adj_index[VLIB_TX] = t0->next_dpo.dpoi_index; /* Get next node index and adj index from tunnel next_dpo */ if (sw_if_index1 != vnet_buffer(b1)->sw_if_index[VLIB_TX]) { sw_if_index1 = vnet_buffer(b1)->sw_if_index[VLIB_TX]; hi1 = vnet_get_sup_hw_interface (vnm, sw_if_index1); t1 = &vxm->tunnels[hi1->dev_instance]; /* Note: change to always set next1 if it may be set to drop */ next1 = t1->next_dpo.dpoi_next_node; } vnet_buffer(b1)->ip.adj_index[VLIB_TX] = t1->next_dpo.dpoi_index; /* Apply the rewrite string. $$$$ vnet_rewrite? */ vlib_buffer_advance (b0, -(word)_vec_len(t0->rewrite)); vlib_buffer_advance (b1, -(word)_vec_len(t1->rewrite)); if (is_ip4) { /* IP4 VXLAN header should be 36 octects */ ASSERT(sizeof(ip4_vxlan_header_t) == 36); ASSERT(vec_len(t0->rewrite) == sizeof(ip4_vxlan_header_t)); ASSERT(vec_len(t1->rewrite) == sizeof(ip4_vxlan_header_t)); ip4_0 = vlib_buffer_get_current(b0); ip4_1 = vlib_buffer_get_current(b1); /* Copy the fixed header */ copy_dst0 = (u64 *) ip4_0; copy_src0 = (u64 *) t0->rewrite; copy_dst1 = (u64 *) ip4_1; copy_src1 = (u64 *) t1->rewrite; /* Copy first 32 octets 8-bytes at a time */ #define _(offs) copy_dst0[offs] = copy_src0[offs]; foreach_fixed_header4_offset; #undef _ #define _(offs) copy_dst1[offs] = copy_src1[offs]; foreach_fixed_header4_offset; #undef _ /* Last 4 octets. Hopefully gcc will be our friend */ copy_dst_last0 = (u32 *)(&copy_dst0[4]); copy_src_last0 = (u32 *)(&copy_src0[4]); copy_dst_last0[0] = copy_src_last0[0]; copy_dst_last1 = (u32 *)(&copy_dst1[4]); copy_src_last1 = (u32 *)(&copy_src1[4]); copy_dst_last1[0] = copy_src_last1[0]; /* Fix the IP4 checksum and length */ sum0 = ip4_0->checksum; new_l0 = /* old_l0 always 0, see the rewrite setup */ clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, length /* changed member */); ip4_0->checksum = ip_csum_fold (sum0); ip4_0->length = new_l0; sum1 = ip4_1->checksum; new_l1 = /* old_l1 always 0, see the rewrite setup */ clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1)); sum1 = ip_csum_update (sum1, old_l1, new_l1, ip4_header_t, length /* changed member */); ip4_1->checksum = ip_csum_fold (sum1); ip4_1->length = new_l1; /* Fix UDP length and set source port */ udp0 = (udp_header_t *)(ip4_0+1); new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b0) - sizeof (*ip4_0)); udp0->length = new_l0; udp0->src_port = flow_hash0; udp1 = (udp_header_t *)(ip4_1+1); new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b1) - sizeof (*ip4_1)); udp1->length = new_l1; udp1->src_port = flow_hash1; } else /* ipv6 */ { int bogus = 0; /* IP6 VXLAN header should be 56 octects */ ASSERT(sizeof(ip6_vxlan_header_t) == 56); ASSERT(vec_len(t0->rewrite) == sizeof(ip6_vxlan_header_t)); ASSERT(vec_len(t1->rewrite) == sizeof(ip6_vxlan_header_t)); ip6_0 = vlib_buffer_get_current(b0); ip6_1 = vlib_buffer_get_current(b1); /* Copy the fixed header */ copy_dst0 = (u64 *) ip6_0; copy_src0 = (u64 *) t0->rewrite; copy_dst1 = (u64 *) ip6_1; copy_src1 = (u64 *) t1->rewrite; /* Copy first 56 (ip6) octets 8-bytes at a time */ #define _(offs) copy_dst0[offs] = copy_src0[offs]; foreach_fixed_header6_offset; #undef _ #define _(offs) copy_dst1[offs] = copy_src1[offs]; foreach_fixed_header6_offset; #undef _ /* Fix IP6 payload length */ new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - sizeof(*ip6_0)); ip6_0->payload_length = new_l0; new_l1 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b1) - sizeof(*ip6_1)); ip6_1->payload_length = new_l1; /* Fix UDP length and set source port */ udp0 = (udp_header_t *)(ip6_0+1); udp0->length = new_l0; udp0->src_port = flow_hash0; udp1 = (udp_header_t *)(ip6_1+1); udp1->length = new_l1; udp1->src_port = flow_hash1; /* IPv6 UDP checksum is mandatory */ udp0->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip6_0, &bogus); ASSERT(bogus == 0); if (udp0->checksum == 0) udp0->checksum = 0xffff; udp1->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b1, ip6_1, &bogus); ASSERT(bogus == 0); if (udp1->checksum == 0) udp1->checksum = 0xffff; } pkts_encapsulated += 2; len0 = vlib_buffer_length_in_chain (vm, b0); len1 = vlib_buffer_length_in_chain (vm, b1); stats_n_packets += 2; stats_n_bytes += len0 + len1; /* Batch stats increment on the same vxlan tunnel so counter is not incremented per packet. Note stats are still incremented for deleted and admin-down tunnel where packets are dropped. It is not worthwhile to check for this rare case and affect normal path performance. */ if (PREDICT_FALSE ((sw_if_index0 != stats_sw_if_index) || (sw_if_index1 != stats_sw_if_index))) { stats_n_packets -= 2; stats_n_bytes -= len0 + len1; if (sw_if_index0 == sw_if_index1) { if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_sw_if_index = sw_if_index0; stats_n_packets = 2; stats_n_bytes = len0 + len1; } else { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, sw_if_index0, 1, len0); vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, sw_if_index1, 1, len1); } } if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { vxlan_encap_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_index = t0 - vxm->tunnels; tr->vni = t0->vni; } if (PREDICT_FALSE(b1->flags & VLIB_BUFFER_IS_TRACED)) { vxlan_encap_trace_t *tr = vlib_add_trace (vm, node, b1, sizeof (*tr)); tr->tunnel_index = t1 - vxm->tunnels; tr->vni = t1->vni; } vlib_validate_buffer_enqueue_x2 (vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1); } while (n_left_from > 0 && n_left_to_next > 0) { u32 bi0; vlib_buffer_t * b0; u32 flow_hash0; u32 len0; ip4_header_t * ip4_0; ip6_header_t * ip6_0; udp_header_t * udp0; u64 * copy_src0, * copy_dst0; u32 * copy_src_last0, * copy_dst_last0; u16 new_l0; ip_csum_t sum0; bi0 = from[0]; to_next[0] = bi0; from += 1; to_next += 1; n_left_from -= 1; n_left_to_next -= 1; b0 = vlib_get_buffer (vm, bi0); flow_hash0 = vnet_l2_compute_flow_hash(b0); /* Get next node index and adj index from tunnel next_dpo */ if (sw_if_index0 != vnet_buffer(b0)->sw_if_index[VLIB_TX]) { sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_TX]; hi0 = vnet_get_sup_hw_interface (vnm, sw_if_index0); t0 = &vxm->tunnels[hi0->dev_instance]; /* Note: change to always set next0 if it may be set to drop */ next0 = t0->next_dpo.dpoi_next_node; } vnet_buffer(b0)->ip.adj_index[VLIB_TX] = t0->next_dpo.dpoi_index; /* Apply the rewrite string. $$$$ vnet_rewrite? */ vlib_buffer_advance (b0, -(word)_vec_len(t0->rewrite)); if (is_ip4) { /* IP4 VXLAN header should be 36 octects */ ASSERT(sizeof(ip4_vxlan_header_t) == 36); ASSERT(vec_len(t0->rewrite) == sizeof(ip4_vxlan_header_t)); ip4_0 = vlib_buffer_get_current(b0); /* Copy the fixed header */ copy_dst0 = (u64 *) ip4_0; copy_src0 = (u64 *) t0->rewrite; /* Copy first 32 octets 8-bytes at a time */ #define _(offs) copy_dst0[offs] = copy_src0[offs]; foreach_fixed_header4_offset; #undef _ /* Last 4 octets. Hopefully gcc will be our friend */ copy_dst_last0 = (u32 *)(&copy_dst0[4]); copy_src_last0 = (u32 *)(&copy_src0[4]); copy_dst_last0[0] = copy_src_last0[0]; /* Fix the IP4 checksum and length */ sum0 = ip4_0->checksum; new_l0 = /* old_l0 always 0, see the rewrite setup */ clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); sum0 = ip_csum_update (sum0, old_l0, new_l0, ip4_header_t, length /* changed member */); ip4_0->checksum = ip_csum_fold (sum0); ip4_0->length = new_l0; /* Fix UDP length and set source port */ udp0 = (udp_header_t *)(ip4_0+1); new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b0) - sizeof (*ip4_0)); udp0->length = new_l0; udp0->src_port = flow_hash0; } else /* ip6 path */ { int bogus = 0; /* IP6 VXLAN header should be 56 octects */ ASSERT(sizeof(ip6_vxlan_header_t) == 56); ASSERT(vec_len(t0->rewrite) == sizeof(ip6_vxlan_header_t)); ip6_0 = vlib_buffer_get_current(b0); /* Copy the fixed header */ copy_dst0 = (u64 *) ip6_0; copy_src0 = (u64 *) t0->rewrite; /* Copy first 56 (ip6) octets 8-bytes at a time */ #define _(offs) copy_dst0[offs] = copy_src0[offs]; foreach_fixed_header6_offset; #undef _ /* Fix IP6 payload length */ new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0) - sizeof(*ip6_0)); ip6_0->payload_length = new_l0; /* Fix UDP length and set source port */ udp0 = (udp_header_t *)(ip6_0+1); udp0->length = new_l0; udp0->src_port = flow_hash0; /* IPv6 UDP checksum is mandatory */ udp0->checksum = ip6_tcp_udp_icmp_compute_checksum(vm, b0, ip6_0, &bogus); ASSERT(bogus == 0); if (udp0->checksum == 0) udp0->checksum = 0xffff; } pkts_encapsulated ++; len0 = vlib_buffer_length_in_chain (vm, b0); stats_n_packets += 1; stats_n_bytes += len0; /* Batch stats increment on the same vxlan tunnel so counter is not incremented per packet. Note stats are still incremented for deleted and admin-down tunnel where packets are dropped. It is not worthwhile to check for this rare case and affect normal path performance. */ if (PREDICT_FALSE (sw_if_index0 != stats_sw_if_index)) { stats_n_packets -= 1; stats_n_bytes -= len0; if (stats_n_packets) vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); stats_n_packets = 1; stats_n_bytes = len0; stats_sw_if_index = sw_if_index0; } if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) { vxlan_encap_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); tr->tunnel_index = t0 - vxm->tunnels; tr->vni = t0->vni; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); } vlib_put_next_frame (vm, node, next_index, n_left_to_next); } /* Do we still need this now that tunnel tx stats is kept? */ vlib_node_increment_counter (vm, node->node_index, VXLAN_ENCAP_ERROR_ENCAPSULATED, pkts_encapsulated); /* Increment any remaining batch stats */ if (stats_n_packets) { vlib_increment_combined_counter (im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX, cpu_index, stats_sw_if_index, stats_n_packets, stats_n_bytes); node->runtime_data[0] = stats_sw_if_index; } return from_frame->n_vectors; } static uword vxlan4_encap (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 1); } static uword vxlan6_encap (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { return vxlan_encap_inline (vm, node, from_frame, /* is_ip4 */ 0); } VLIB_REGISTER_NODE (vxlan4_encap_node) = { .function = vxlan4_encap, .name = "vxlan4-encap", .vector_size = sizeof (u32), .format_trace = format_vxlan_encap_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN(vxlan_encap_error_strings), .error_strings = vxlan_encap_error_strings, .n_next_nodes = VXLAN_ENCAP_N_NEXT, .next_nodes = { [VXLAN_ENCAP_NEXT_DROP] = "error-drop", }, }; VLIB_NODE_FUNCTION_MULTIARCH (vxlan4_encap_node, vxlan4_encap) VLIB_REGISTER_NODE (vxlan6_encap_node) = { .function = vxlan6_encap, .name = "vxlan6-encap", .vector_size = sizeof (u32), .format_trace = format_vxlan_encap_trace, .type = VLIB_NODE_TYPE_INTERNAL, .n_errors = ARRAY_LEN(vxlan_encap_error_strings), .error_strings = vxlan_encap_error_strings, .n_next_nodes = VXLAN_ENCAP_N_NEXT, .next_nodes = { [VXLAN_ENCAP_NEXT_DROP] = "error-drop", }, }; VLIB_NODE_FUNCTION_MULTIARCH (vxlan6_encap_node, vxlan6_encap)