- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (0);
-#define _(a) else if (unformat (input, #a)) a=1;
- foreach_udp_proto_field
-#undef _
- else
- break;
- }
-
-#define _(a) found_something += a;
- foreach_udp_proto_field;
-#undef _
-
- if (found_something == 0)
- return 0;
-
- vec_validate (mask, sizeof (*udp) - 1);
-
- udp = (udp_header_t *) mask;
-
-#define _(a) if (a) memset (&udp->a, 0xff, sizeof (udp->a));
- foreach_udp_proto_field;
-#undef _
-
- *maskp = mask;
- return 1;
-}
-
-uword
-unformat_l4_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
- u16 src_port = 0, dst_port = 0;
- tcpudp_header_t *tcpudp;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "tcp %U", unformat_tcp_mask, maskp))
- return 1;
- else if (unformat (input, "udp %U", unformat_udp_mask, maskp))
- return 1;
- else if (unformat (input, "src_port"))
- src_port = 0xFFFF;
- else if (unformat (input, "dst_port"))
- dst_port = 0xFFFF;
- else
- return 0;
- }
-
- if (!src_port && !dst_port)
- return 0;
-
- u8 *mask = 0;
- vec_validate (mask, sizeof (tcpudp_header_t) - 1);
-
- tcpudp = (tcpudp_header_t *) mask;
- tcpudp->src_port = src_port;
- tcpudp->dst_port = dst_port;
-
- *maskp = mask;
-
- return 1;
-}
-
-uword
-unformat_ip4_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
- u8 *mask = 0;
- u8 found_something = 0;
- ip4_header_t *ip;
-
-#define _(a) u8 a=0;
- foreach_ip4_proto_field;
-#undef _
- u8 version = 0;
- u8 hdr_length = 0;
-
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "version"))
- version = 1;
- else if (unformat (input, "hdr_length"))
- hdr_length = 1;
- else if (unformat (input, "src"))
- src_address = 1;
- else if (unformat (input, "dst"))
- dst_address = 1;
- else if (unformat (input, "proto"))
- protocol = 1;
-
-#define _(a) else if (unformat (input, #a)) a=1;
- foreach_ip4_proto_field
-#undef _
- else
- break;
- }
-
-#define _(a) found_something += a;
- foreach_ip4_proto_field;
-#undef _
-
- if (found_something == 0)
- return 0;
-
- vec_validate (mask, sizeof (*ip) - 1);
-
- ip = (ip4_header_t *) mask;
-
-#define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
- foreach_ip4_proto_field;
-#undef _
-
- ip->ip_version_and_header_length = 0;
-
- if (version)
- ip->ip_version_and_header_length |= 0xF0;
-
- if (hdr_length)
- ip->ip_version_and_header_length |= 0x0F;
-
- *maskp = mask;
- return 1;
-}
-
-#define foreach_ip6_proto_field \
-_(src_address) \
-_(dst_address) \
-_(payload_length) \
-_(hop_limit) \
-_(protocol)
-
-uword
-unformat_ip6_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
- u8 *mask = 0;
- u8 found_something = 0;
- ip6_header_t *ip;
- u32 ip_version_traffic_class_and_flow_label;
-
-#define _(a) u8 a=0;
- foreach_ip6_proto_field;
-#undef _
- u8 version = 0;
- u8 traffic_class = 0;
- u8 flow_label = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "version"))
- version = 1;
- else if (unformat (input, "traffic-class"))
- traffic_class = 1;
- else if (unformat (input, "flow-label"))
- flow_label = 1;
- else if (unformat (input, "src"))
- src_address = 1;
- else if (unformat (input, "dst"))
- dst_address = 1;
- else if (unformat (input, "proto"))
- protocol = 1;
-
-#define _(a) else if (unformat (input, #a)) a=1;
- foreach_ip6_proto_field
-#undef _
- else
- break;
- }
-
-#define _(a) found_something += a;
- foreach_ip6_proto_field;
-#undef _
-
- if (found_something == 0)
- return 0;
-
- vec_validate (mask, sizeof (*ip) - 1);
-
- ip = (ip6_header_t *) mask;
-
-#define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a));
- foreach_ip6_proto_field;
-#undef _
-
- ip_version_traffic_class_and_flow_label = 0;
-
- if (version)
- ip_version_traffic_class_and_flow_label |= 0xF0000000;
-
- if (traffic_class)
- ip_version_traffic_class_and_flow_label |= 0x0FF00000;
-
- if (flow_label)
- ip_version_traffic_class_and_flow_label |= 0x000FFFFF;
-
- ip->ip_version_traffic_class_and_flow_label =
- clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
-
- *maskp = mask;
- return 1;
-}
-
-uword
-unformat_l3_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp))
- return 1;
- else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp))
- return 1;
- else
- break;
- }
- return 0;
-}
-
-uword
-unformat_l2_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
- u8 *mask = 0;
- u8 src = 0;
- u8 dst = 0;
- u8 proto = 0;
- u8 tag1 = 0;
- u8 tag2 = 0;
- u8 ignore_tag1 = 0;
- u8 ignore_tag2 = 0;
- u8 cos1 = 0;
- u8 cos2 = 0;
- u8 dot1q = 0;
- u8 dot1ad = 0;
- int len = 14;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "src"))
- src = 1;
- else if (unformat (input, "dst"))
- dst = 1;
- else if (unformat (input, "proto"))
- proto = 1;
- else if (unformat (input, "tag1"))
- tag1 = 1;
- else if (unformat (input, "tag2"))
- tag2 = 1;
- else if (unformat (input, "ignore-tag1"))
- ignore_tag1 = 1;
- else if (unformat (input, "ignore-tag2"))
- ignore_tag2 = 1;
- else if (unformat (input, "cos1"))
- cos1 = 1;
- else if (unformat (input, "cos2"))
- cos2 = 1;
- else if (unformat (input, "dot1q"))
- dot1q = 1;
- else if (unformat (input, "dot1ad"))
- dot1ad = 1;
- else
- break;
- }
- if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad +
- ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
- return 0;
-
- if (tag1 || ignore_tag1 || cos1 || dot1q)
- len = 18;
- if (tag2 || ignore_tag2 || cos2 || dot1ad)
- len = 22;
-
- vec_validate (mask, len - 1);
-
- if (dst)
- memset (mask, 0xff, 6);
-
- if (src)
- memset (mask + 6, 0xff, 6);
-
- if (tag2 || dot1ad)
- {
- /* inner vlan tag */
- if (tag2)
- {
- mask[19] = 0xff;
- mask[18] = 0x0f;
- }
- if (cos2)
- mask[18] |= 0xe0;
- if (proto)
- mask[21] = mask[20] = 0xff;
- if (tag1)
- {
- mask[15] = 0xff;
- mask[14] = 0x0f;
- }
- if (cos1)
- mask[14] |= 0xe0;
- *maskp = mask;
- return 1;
- }
- if (tag1 | dot1q)
- {
- if (tag1)
- {
- mask[15] = 0xff;
- mask[14] = 0x0f;
- }
- if (cos1)
- mask[14] |= 0xe0;
- if (proto)
- mask[16] = mask[17] = 0xff;
-
- *maskp = mask;
- return 1;
- }
- if (cos2)
- mask[18] |= 0xe0;
- if (cos1)
- mask[14] |= 0xe0;
- if (proto)
- mask[12] = mask[13] = 0xff;
-
- *maskp = mask;
- return 1;
-}
-
-uword
-unformat_classify_mask (unformat_input_t * input, va_list * args)
-{
- u8 **maskp = va_arg (*args, u8 **);
- u32 *skipp = va_arg (*args, u32 *);
- u32 *matchp = va_arg (*args, u32 *);
- u32 match;
- u8 *mask = 0;
- u8 *l2 = 0;
- u8 *l3 = 0;
- u8 *l4 = 0;
- int i;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "hex %U", unformat_hex_string, &mask))
- ;
- else if (unformat (input, "l2 %U", unformat_l2_mask, &l2))
- ;
- else if (unformat (input, "l3 %U", unformat_l3_mask, &l3))
- ;
- else if (unformat (input, "l4 %U", unformat_l4_mask, &l4))
- ;
- else
- break;
- }
-
- if (l4 && !l3)
- {
- vec_free (mask);
- vec_free (l2);
- vec_free (l4);
- return 0;
- }
-
- if (mask || l2 || l3 || l4)
- {
- if (l2 || l3 || l4)
- {
- /* "With a free Ethernet header in every package" */
- if (l2 == 0)
- vec_validate (l2, 13);
- mask = l2;
- if (vec_len (l3))
- {
- vec_append (mask, l3);
- vec_free (l3);
- }
- if (vec_len (l4))
- {
- vec_append (mask, l4);
- vec_free (l4);
- }
- }
-
- /* Scan forward looking for the first significant mask octet */
- for (i = 0; i < vec_len (mask); i++)
- if (mask[i])
- break;
-
- /* compute (skip, match) params */
- *skipp = i / sizeof (u32x4);
- vec_delete (mask, *skipp * sizeof (u32x4), 0);
-
- /* Pad mask to an even multiple of the vector size */
- while (vec_len (mask) % sizeof (u32x4))
- vec_add1 (mask, 0);
-
- match = vec_len (mask) / sizeof (u32x4);
-
- for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4))
- {
- u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4)));
- if (*tmp || *(tmp + 1))
- break;
- match--;
- }
- if (match == 0)
- clib_warning ("BUG: match 0");
-
- _vec_len (mask) = match * sizeof (u32x4);
-
- *matchp = match;
- *maskp = mask;
-
- return 1;
- }
-
- return 0;
-}
-#endif /* VPP_API_TEST_BUILTIN */
-
-#define foreach_l2_next \
-_(drop, DROP) \
-_(ethernet, ETHERNET_INPUT) \
-_(ip4, IP4_INPUT) \
-_(ip6, IP6_INPUT)
-
-uword
-unformat_l2_next_index (unformat_input_t * input, va_list * args)
-{
- u32 *miss_next_indexp = va_arg (*args, u32 *);
- u32 next_index = 0;
- u32 tmp;
-
-#define _(n,N) \
- if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;}
- foreach_l2_next;
-#undef _
-
- if (unformat (input, "%d", &tmp))
- {
- next_index = tmp;
- goto out;
- }
-
- return 0;
-
-out:
- *miss_next_indexp = next_index;
- return 1;
-}
-
-#define foreach_ip_next \
-_(drop, DROP) \
-_(local, LOCAL) \
-_(rewrite, REWRITE)
-
-uword
-api_unformat_ip_next_index (unformat_input_t * input, va_list * args)
-{
- u32 *miss_next_indexp = va_arg (*args, u32 *);
- u32 next_index = 0;
- u32 tmp;
-
-#define _(n,N) \
- if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;}
- foreach_ip_next;
-#undef _
-
- if (unformat (input, "%d", &tmp))
- {
- next_index = tmp;
- goto out;
- }
-
- return 0;
-
-out:
- *miss_next_indexp = next_index;
- return 1;
-}
-
-#define foreach_acl_next \
-_(deny, DENY)
-
-uword
-api_unformat_acl_next_index (unformat_input_t * input, va_list * args)
-{
- u32 *miss_next_indexp = va_arg (*args, u32 *);
- u32 next_index = 0;
- u32 tmp;
-
-#define _(n,N) \
- if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;}
- foreach_acl_next;
-#undef _
-
- if (unformat (input, "permit"))
- {
- next_index = ~0;
- goto out;
- }
- else if (unformat (input, "%d", &tmp))
- {
- next_index = tmp;
- goto out;
- }
-
- return 0;
-
-out:
- *miss_next_indexp = next_index;
- return 1;
-}
-
-uword
-unformat_policer_precolor (unformat_input_t * input, va_list * args)
-{
- u32 *r = va_arg (*args, u32 *);
-
- if (unformat (input, "conform-color"))
- *r = POLICE_CONFORM;
- else if (unformat (input, "exceed-color"))
- *r = POLICE_EXCEED;
- else
- return 0;
-
- return 1;
-}
-
-static int
-api_classify_add_del_table (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_classify_add_del_table_t *mp;
-
- u32 nbuckets = 2;
- u32 skip = ~0;
- u32 match = ~0;
- int is_add = 1;
- int del_chain = 0;
- u32 table_index = ~0;
- u32 next_table_index = ~0;
- u32 miss_next_index = ~0;
- u32 memory_size = 32 << 20;
- u8 *mask = 0;
- u32 current_data_flag = 0;
- int current_data_offset = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "del"))
- is_add = 0;
- else if (unformat (i, "del-chain"))
- {
- is_add = 0;
- del_chain = 1;
- }
- else if (unformat (i, "buckets %d", &nbuckets))
- ;
- else if (unformat (i, "memory_size %d", &memory_size))
- ;
- else if (unformat (i, "skip %d", &skip))
- ;
- else if (unformat (i, "match %d", &match))
- ;
- else if (unformat (i, "table %d", &table_index))
- ;
- else if (unformat (i, "mask %U", unformat_classify_mask,
- &mask, &skip, &match))
- ;
- else if (unformat (i, "next-table %d", &next_table_index))
- ;
- else if (unformat (i, "miss-next %U", api_unformat_ip_next_index,
- &miss_next_index))
- ;
- else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index,
- &miss_next_index))
- ;
- else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index,
- &miss_next_index))
- ;
- else if (unformat (i, "current-data-flag %d", ¤t_data_flag))
- ;
- else if (unformat (i, "current-data-offset %d", ¤t_data_offset))
- ;
- else
- break;
- }
-
- if (is_add && mask == 0)
- {
- errmsg ("Mask required");
- return -99;
- }
-
- if (is_add && skip == ~0)
- {
- errmsg ("skip count required");
- return -99;
- }
-
- if (is_add && match == ~0)
- {
- errmsg ("match count required");
- return -99;
- }
-
- if (!is_add && table_index == ~0)
- {
- errmsg ("table index required for delete");
- return -99;
- }
-
- M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask));
-
- mp->is_add = is_add;
- mp->del_chain = del_chain;
- mp->table_index = ntohl (table_index);
- mp->nbuckets = ntohl (nbuckets);
- mp->memory_size = ntohl (memory_size);
- mp->skip_n_vectors = ntohl (skip);
- mp->match_n_vectors = ntohl (match);
- mp->next_table_index = ntohl (next_table_index);
- mp->miss_next_index = ntohl (miss_next_index);
- mp->current_data_flag = ntohl (current_data_flag);
- mp->current_data_offset = ntohl (current_data_offset);
- clib_memcpy (mp->mask, mask, vec_len (mask));
-
- vec_free (mask);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-#if VPP_API_TEST_BUILTIN == 0
-uword
-unformat_l4_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
-
- u8 *proto_header = 0;
- int src_port = 0;
- int dst_port = 0;
-
- tcpudp_header_t h;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "src_port %d", &src_port))
- ;
- else if (unformat (input, "dst_port %d", &dst_port))
- ;
- else
- return 0;
- }
-
- h.src_port = clib_host_to_net_u16 (src_port);
- h.dst_port = clib_host_to_net_u16 (dst_port);
- vec_validate (proto_header, sizeof (h) - 1);
- memcpy (proto_header, &h, sizeof (h));
-
- *matchp = proto_header;
-
- return 1;
-}
-
-uword
-unformat_ip4_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
- u8 *match = 0;
- ip4_header_t *ip;
- int version = 0;
- u32 version_val;
- int hdr_length = 0;
- u32 hdr_length_val;
- int src = 0, dst = 0;
- ip4_address_t src_val, dst_val;
- int proto = 0;
- u32 proto_val;
- int tos = 0;
- u32 tos_val;
- int length = 0;
- u32 length_val;
- int fragment_id = 0;
- u32 fragment_id_val;
- int ttl = 0;
- int ttl_val;
- int checksum = 0;
- u32 checksum_val;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "version %d", &version_val))
- version = 1;
- else if (unformat (input, "hdr_length %d", &hdr_length_val))
- hdr_length = 1;
- else if (unformat (input, "src %U", unformat_ip4_address, &src_val))
- src = 1;
- else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val))
- dst = 1;
- else if (unformat (input, "proto %d", &proto_val))
- proto = 1;
- else if (unformat (input, "tos %d", &tos_val))
- tos = 1;
- else if (unformat (input, "length %d", &length_val))
- length = 1;
- else if (unformat (input, "fragment_id %d", &fragment_id_val))
- fragment_id = 1;
- else if (unformat (input, "ttl %d", &ttl_val))
- ttl = 1;
- else if (unformat (input, "checksum %d", &checksum_val))
- checksum = 1;
- else
- break;
- }
-
- if (version + hdr_length + src + dst + proto + tos + length + fragment_id
- + ttl + checksum == 0)
- return 0;
-
- /*
- * Aligned because we use the real comparison functions
- */
- vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
-
- ip = (ip4_header_t *) match;
-
- /* These are realistically matched in practice */
- if (src)
- ip->src_address.as_u32 = src_val.as_u32;
-
- if (dst)
- ip->dst_address.as_u32 = dst_val.as_u32;
-
- if (proto)
- ip->protocol = proto_val;
-
-
- /* These are not, but they're included for completeness */
- if (version)
- ip->ip_version_and_header_length |= (version_val & 0xF) << 4;
-
- if (hdr_length)
- ip->ip_version_and_header_length |= (hdr_length_val & 0xF);
-
- if (tos)
- ip->tos = tos_val;
-
- if (length)
- ip->length = clib_host_to_net_u16 (length_val);
-
- if (ttl)
- ip->ttl = ttl_val;
-
- if (checksum)
- ip->checksum = clib_host_to_net_u16 (checksum_val);
-
- *matchp = match;
- return 1;
-}
-
-uword
-unformat_ip6_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
- u8 *match = 0;
- ip6_header_t *ip;
- int version = 0;
- u32 version_val;
- u8 traffic_class = 0;
- u32 traffic_class_val = 0;
- u8 flow_label = 0;
- u8 flow_label_val;
- int src = 0, dst = 0;
- ip6_address_t src_val, dst_val;
- int proto = 0;
- u32 proto_val;
- int payload_length = 0;
- u32 payload_length_val;
- int hop_limit = 0;
- int hop_limit_val;
- u32 ip_version_traffic_class_and_flow_label;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "version %d", &version_val))
- version = 1;
- else if (unformat (input, "traffic_class %d", &traffic_class_val))
- traffic_class = 1;
- else if (unformat (input, "flow_label %d", &flow_label_val))
- flow_label = 1;
- else if (unformat (input, "src %U", unformat_ip6_address, &src_val))
- src = 1;
- else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val))
- dst = 1;
- else if (unformat (input, "proto %d", &proto_val))
- proto = 1;
- else if (unformat (input, "payload_length %d", &payload_length_val))
- payload_length = 1;
- else if (unformat (input, "hop_limit %d", &hop_limit_val))
- hop_limit = 1;
- else
- break;
- }
-
- if (version + traffic_class + flow_label + src + dst + proto +
- payload_length + hop_limit == 0)
- return 0;
-
- /*
- * Aligned because we use the real comparison functions
- */
- vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4));
-
- ip = (ip6_header_t *) match;
-
- if (src)
- clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address));
-
- if (dst)
- clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address));
-
- if (proto)
- ip->protocol = proto_val;
-
- ip_version_traffic_class_and_flow_label = 0;
-
- if (version)
- ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28;
-
- if (traffic_class)
- ip_version_traffic_class_and_flow_label |=
- (traffic_class_val & 0xFF) << 20;
-
- if (flow_label)
- ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF);
-
- ip->ip_version_traffic_class_and_flow_label =
- clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label);
-
- if (payload_length)
- ip->payload_length = clib_host_to_net_u16 (payload_length_val);
-
- if (hop_limit)
- ip->hop_limit = hop_limit_val;
-
- *matchp = match;
- return 1;
-}
-
-uword
-unformat_l3_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "ip4 %U", unformat_ip4_match, matchp))
- return 1;
- else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp))
- return 1;
- else
- break;
- }
- return 0;
-}
-
-uword
-unformat_vlan_tag (unformat_input_t * input, va_list * args)
-{
- u8 *tagp = va_arg (*args, u8 *);
- u32 tag;
-
- if (unformat (input, "%d", &tag))
- {
- tagp[0] = (tag >> 8) & 0x0F;
- tagp[1] = tag & 0xFF;
- return 1;
- }
-
- return 0;
-}
-
-uword
-unformat_l2_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
- u8 *match = 0;
- u8 src = 0;
- u8 src_val[6];
- u8 dst = 0;
- u8 dst_val[6];
- u8 proto = 0;
- u16 proto_val;
- u8 tag1 = 0;
- u8 tag1_val[2];
- u8 tag2 = 0;
- u8 tag2_val[2];
- int len = 14;
- u8 ignore_tag1 = 0;
- u8 ignore_tag2 = 0;
- u8 cos1 = 0;
- u8 cos2 = 0;
- u32 cos1_val = 0;
- u32 cos2_val = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "src %U", unformat_ethernet_address, &src_val))
- src = 1;
- else
- if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val))
- dst = 1;
- else if (unformat (input, "proto %U",
- unformat_ethernet_type_host_byte_order, &proto_val))
- proto = 1;
- else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val))
- tag1 = 1;
- else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val))
- tag2 = 1;
- else if (unformat (input, "ignore-tag1"))
- ignore_tag1 = 1;
- else if (unformat (input, "ignore-tag2"))
- ignore_tag2 = 1;
- else if (unformat (input, "cos1 %d", &cos1_val))
- cos1 = 1;
- else if (unformat (input, "cos2 %d", &cos2_val))
- cos2 = 1;
- else
- break;
- }
- if ((src + dst + proto + tag1 + tag2 +
- ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0)
- return 0;
-
- if (tag1 || ignore_tag1 || cos1)
- len = 18;
- if (tag2 || ignore_tag2 || cos2)
- len = 22;
-
- vec_validate_aligned (match, len - 1, sizeof (u32x4));
-
- if (dst)
- clib_memcpy (match, dst_val, 6);
-
- if (src)
- clib_memcpy (match + 6, src_val, 6);
-
- if (tag2)
- {
- /* inner vlan tag */
- match[19] = tag2_val[1];
- match[18] = tag2_val[0];
- if (cos2)
- match[18] |= (cos2_val & 0x7) << 5;
- if (proto)
- {
- match[21] = proto_val & 0xff;
- match[20] = proto_val >> 8;
- }
- if (tag1)
- {
- match[15] = tag1_val[1];
- match[14] = tag1_val[0];
- }
- if (cos1)
- match[14] |= (cos1_val & 0x7) << 5;
- *matchp = match;
- return 1;
- }
- if (tag1)
- {
- match[15] = tag1_val[1];
- match[14] = tag1_val[0];
- if (proto)
- {
- match[17] = proto_val & 0xff;
- match[16] = proto_val >> 8;
- }
- if (cos1)
- match[14] |= (cos1_val & 0x7) << 5;
-
- *matchp = match;
- return 1;
- }
- if (cos2)
- match[18] |= (cos2_val & 0x7) << 5;
- if (cos1)
- match[14] |= (cos1_val & 0x7) << 5;
- if (proto)
- {
- match[13] = proto_val & 0xff;
- match[12] = proto_val >> 8;
- }
-
- *matchp = match;
- return 1;
-}
-#endif
-
-uword
-api_unformat_classify_match (unformat_input_t * input, va_list * args)
-{
- u8 **matchp = va_arg (*args, u8 **);
- u32 skip_n_vectors = va_arg (*args, u32);
- u32 match_n_vectors = va_arg (*args, u32);
-
- u8 *match = 0;
- u8 *l2 = 0;
- u8 *l3 = 0;
- u8 *l4 = 0;
-
- while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (input, "hex %U", unformat_hex_string, &match))
- ;
- else if (unformat (input, "l2 %U", unformat_l2_match, &l2))
- ;
- else if (unformat (input, "l3 %U", unformat_l3_match, &l3))
- ;
- else if (unformat (input, "l4 %U", unformat_l4_match, &l4))
- ;
- else
- break;
- }
-
- if (l4 && !l3)
- {
- vec_free (match);
- vec_free (l2);
- vec_free (l4);
- return 0;
- }
-
- if (match || l2 || l3 || l4)
- {
- if (l2 || l3 || l4)
- {
- /* "Win a free Ethernet header in every packet" */
- if (l2 == 0)
- vec_validate_aligned (l2, 13, sizeof (u32x4));
- match = l2;
- if (vec_len (l3))
- {
- vec_append_aligned (match, l3, sizeof (u32x4));
- vec_free (l3);
- }
- if (vec_len (l4))
- {
- vec_append_aligned (match, l4, sizeof (u32x4));
- vec_free (l4);
- }
- }
-
- /* Make sure the vector is big enough even if key is all 0's */
- vec_validate_aligned
- (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1,
- sizeof (u32x4));
-
- /* Set size, include skipped vectors */
- _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4);
-
- *matchp = match;
-
- return 1;
- }
-
- return 0;
-}
-
-static int
-api_classify_add_del_session (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_classify_add_del_session_t *mp;
- int is_add = 1;
- u32 table_index = ~0;
- u32 hit_next_index = ~0;
- u32 opaque_index = ~0;
- u8 *match = 0;
- i32 advance = 0;
- u32 skip_n_vectors = 0;
- u32 match_n_vectors = 0;
- u32 action = 0;
- u32 metadata = 0;
- int ret;
-
- /*
- * Warning: you have to supply skip_n and match_n
- * because the API client cant simply look at the classify
- * table object.
- */
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "del"))
- is_add = 0;
- else if (unformat (i, "hit-next %U", api_unformat_ip_next_index,
- &hit_next_index))
- ;
- else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index,
- &hit_next_index))
- ;
- else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index,
- &hit_next_index))
- ;
- else if (unformat (i, "policer-hit-next %d", &hit_next_index))
- ;
- else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index))
- ;
- else if (unformat (i, "opaque-index %d", &opaque_index))
- ;
- else if (unformat (i, "skip_n %d", &skip_n_vectors))
- ;
- else if (unformat (i, "match_n %d", &match_n_vectors))
- ;
- else if (unformat (i, "match %U", api_unformat_classify_match,
- &match, skip_n_vectors, match_n_vectors))
- ;
- else if (unformat (i, "advance %d", &advance))
- ;
- else if (unformat (i, "table-index %d", &table_index))
- ;
- else if (unformat (i, "action set-ip4-fib-id %d", &metadata))
- action = 1;
- else if (unformat (i, "action set-ip6-fib-id %d", &metadata))
- action = 2;
- else if (unformat (i, "action %d", &action))
- ;
- else if (unformat (i, "metadata %d", &metadata))
- ;
- else
- break;
- }
-
- if (table_index == ~0)
- {
- errmsg ("Table index required");
- return -99;
- }
-
- if (is_add && match == 0)
- {
- errmsg ("Match value required");
- return -99;
- }
-
- M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match));
-
- mp->is_add = is_add;
- mp->table_index = ntohl (table_index);
- mp->hit_next_index = ntohl (hit_next_index);
- mp->opaque_index = ntohl (opaque_index);
- mp->advance = ntohl (advance);
- mp->action = action;
- mp->metadata = ntohl (metadata);
- clib_memcpy (mp->match, match, vec_len (match));
- vec_free (match);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_classify_set_interface_ip_table (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_classify_set_interface_ip_table_t *mp;
- u32 sw_if_index;
- int sw_if_index_set;
- u32 table_index = ~0;
- u8 is_ipv6 = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "table %d", &table_index))
- ;
- else
- {
- clib_warning ("parse error '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (sw_if_index_set == 0)
- {
- errmsg ("missing interface name or sw_if_index");
- return -99;
- }
-
-
- M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp);
-
- mp->sw_if_index = ntohl (sw_if_index);
- mp->table_index = ntohl (table_index);
- mp->is_ipv6 = is_ipv6;
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_classify_set_interface_l2_tables (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_classify_set_interface_l2_tables_t *mp;
- u32 sw_if_index;
- int sw_if_index_set;
- u32 ip4_table_index = ~0;
- u32 ip6_table_index = ~0;
- u32 other_table_index = ~0;
- u32 is_input = 1;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "ip4-table %d", &ip4_table_index))
- ;
- else if (unformat (i, "ip6-table %d", &ip6_table_index))
- ;
- else if (unformat (i, "other-table %d", &other_table_index))
- ;
- else if (unformat (i, "is-input %d", &is_input))
- ;
- else
- {
- clib_warning ("parse error '%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (sw_if_index_set == 0)
- {
- errmsg ("missing interface name or sw_if_index");
- return -99;
- }
-
-
- M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp);
-
- mp->sw_if_index = ntohl (sw_if_index);
- mp->ip4_table_index = ntohl (ip4_table_index);
- mp->ip6_table_index = ntohl (ip6_table_index);
- mp->other_table_index = ntohl (other_table_index);
- mp->is_input = (u8) is_input;
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_set_ipfix_exporter (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_set_ipfix_exporter_t *mp;
- ip4_address_t collector_address;
- u8 collector_address_set = 0;
- u32 collector_port = ~0;
- ip4_address_t src_address;
- u8 src_address_set = 0;
- u32 vrf_id = ~0;
- u32 path_mtu = ~0;
- u32 template_interval = ~0;
- u8 udp_checksum = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "collector_address %U", unformat_ip4_address,
- &collector_address))
- collector_address_set = 1;
- else if (unformat (i, "collector_port %d", &collector_port))
- ;
- else if (unformat (i, "src_address %U", unformat_ip4_address,
- &src_address))
- src_address_set = 1;
- else if (unformat (i, "vrf_id %d", &vrf_id))
- ;
- else if (unformat (i, "path_mtu %d", &path_mtu))
- ;
- else if (unformat (i, "template_interval %d", &template_interval))
- ;
- else if (unformat (i, "udp_checksum"))
- udp_checksum = 1;
- else
- break;
- }
-
- if (collector_address_set == 0)
- {
- errmsg ("collector_address required");
- return -99;
- }
-
- if (src_address_set == 0)
- {
- errmsg ("src_address required");
- return -99;
- }
-
- M (SET_IPFIX_EXPORTER, mp);
-
- memcpy (mp->collector_address, collector_address.data,
- sizeof (collector_address.data));
- mp->collector_port = htons ((u16) collector_port);
- memcpy (mp->src_address, src_address.data, sizeof (src_address.data));
- mp->vrf_id = htonl (vrf_id);
- mp->path_mtu = htonl (path_mtu);
- mp->template_interval = htonl (template_interval);
- mp->udp_checksum = udp_checksum;
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_set_ipfix_classify_stream (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_set_ipfix_classify_stream_t *mp;
- u32 domain_id = 0;
- u32 src_port = UDP_DST_PORT_ipfix;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "domain %d", &domain_id))
- ;
- else if (unformat (i, "src_port %d", &src_port))
- ;
- else
- {
- errmsg ("unknown input `%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- M (SET_IPFIX_CLASSIFY_STREAM, mp);
-
- mp->domain_id = htonl (domain_id);
- mp->src_port = htons ((u16) src_port);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_ipfix_classify_table_add_del (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_ipfix_classify_table_add_del_t *mp;
- int is_add = -1;
- u32 classify_table_index = ~0;
- u8 ip_version = 0;
- u8 transport_protocol = 255;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "add"))
- is_add = 1;
- else if (unformat (i, "del"))
- is_add = 0;
- else if (unformat (i, "table %d", &classify_table_index))
- ;
- else if (unformat (i, "ip4"))
- ip_version = 4;
- else if (unformat (i, "ip6"))
- ip_version = 6;
- else if (unformat (i, "tcp"))
- transport_protocol = 6;
- else if (unformat (i, "udp"))
- transport_protocol = 17;
- else
- {
- errmsg ("unknown input `%U'", format_unformat_error, i);
- return -99;
- }
- }
-
- if (is_add == -1)
- {
- errmsg ("expecting: add|del");
- return -99;
- }
- if (classify_table_index == ~0)
- {
- errmsg ("classifier table not specified");
- return -99;
- }
- if (ip_version == 0)
- {
- errmsg ("IP version not specified");
- return -99;
- }
-
- M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp);
-
- mp->is_add = is_add;
- mp->table_id = htonl (classify_table_index);
- mp->ip_version = ip_version;
- mp->transport_protocol = transport_protocol;
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_get_node_index (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_get_node_index_t *mp;
- u8 *name = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "node %s", &name))
- ;
- else
- break;
- }
- if (name == 0)
- {
- errmsg ("node name required");
- return -99;
- }
- if (vec_len (name) >= ARRAY_LEN (mp->node_name))
- {
- errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
- return -99;
- }
-
- M (GET_NODE_INDEX, mp);
- clib_memcpy (mp->node_name, name, vec_len (name));
- vec_free (name);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_get_next_index (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_get_next_index_t *mp;
- u8 *node_name = 0, *next_node_name = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "node-name %s", &node_name))
- ;
- else if (unformat (i, "next-node-name %s", &next_node_name))
- break;
- }
-
- if (node_name == 0)
- {
- errmsg ("node name required");
- return -99;
- }
- if (vec_len (node_name) >= ARRAY_LEN (mp->node_name))
- {
- errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
- return -99;
- }
-
- if (next_node_name == 0)
- {
- errmsg ("next node name required");
- return -99;
- }
- if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name))
- {
- errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name));
- return -99;
- }
-
- M (GET_NEXT_INDEX, mp);
- clib_memcpy (mp->node_name, node_name, vec_len (node_name));
- clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name));
- vec_free (node_name);
- vec_free (next_node_name);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_add_node_next (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- vl_api_add_node_next_t *mp;
- u8 *name = 0;
- u8 *next = 0;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "node %s", &name))
- ;
- else if (unformat (i, "next %s", &next))
- ;
- else
- break;
- }
- if (name == 0)
- {
- errmsg ("node name required");
- return -99;
- }
- if (vec_len (name) >= ARRAY_LEN (mp->node_name))
- {
- errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name));
- return -99;
- }
- if (next == 0)
- {
- errmsg ("next node required");
- return -99;
- }
- if (vec_len (next) >= ARRAY_LEN (mp->next_name))
- {
- errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name));
- return -99;
- }
-
- M (ADD_NODE_NEXT, mp);
- clib_memcpy (mp->node_name, name, vec_len (name));
- clib_memcpy (mp->next_name, next, vec_len (next));
- vec_free (name);
- vec_free (next);
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_l2tpv3_create_tunnel (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- ip6_address_t client_address, our_address;
- int client_address_set = 0;
- int our_address_set = 0;
- u32 local_session_id = 0;
- u32 remote_session_id = 0;
- u64 local_cookie = 0;
- u64 remote_cookie = 0;
- u8 l2_sublayer_present = 0;
- vl_api_l2tpv3_create_tunnel_t *mp;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "client_address %U", unformat_ip6_address,
- &client_address))
- client_address_set = 1;
- else if (unformat (i, "our_address %U", unformat_ip6_address,
- &our_address))
- our_address_set = 1;
- else if (unformat (i, "local_session_id %d", &local_session_id))
- ;
- else if (unformat (i, "remote_session_id %d", &remote_session_id))
- ;
- else if (unformat (i, "local_cookie %lld", &local_cookie))
- ;
- else if (unformat (i, "remote_cookie %lld", &remote_cookie))
- ;
- else if (unformat (i, "l2-sublayer-present"))
- l2_sublayer_present = 1;
- else
- break;
- }
-
- if (client_address_set == 0)
- {
- errmsg ("client_address required");
- return -99;
- }
-
- if (our_address_set == 0)
- {
- errmsg ("our_address required");
- return -99;
- }
-
- M (L2TPV3_CREATE_TUNNEL, mp);
-
- clib_memcpy (mp->client_address, client_address.as_u8,
- sizeof (mp->client_address));
-
- clib_memcpy (mp->our_address, our_address.as_u8, sizeof (mp->our_address));
-
- mp->local_session_id = ntohl (local_session_id);
- mp->remote_session_id = ntohl (remote_session_id);
- mp->local_cookie = clib_host_to_net_u64 (local_cookie);
- mp->remote_cookie = clib_host_to_net_u64 (remote_cookie);
- mp->l2_sublayer_present = l2_sublayer_present;
- mp->is_ipv6 = 1;
-
- S (mp);
- W (ret);
- return ret;
-}
-
-static int
-api_l2tpv3_set_tunnel_cookies (vat_main_t * vam)
-{
- unformat_input_t *i = vam->input;
- u32 sw_if_index;
- u8 sw_if_index_set = 0;
- u64 new_local_cookie = 0;
- u64 new_remote_cookie = 0;
- vl_api_l2tpv3_set_tunnel_cookies_t *mp;
- int ret;
-
- while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
- {
- if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "sw_if_index %d", &sw_if_index))
- sw_if_index_set = 1;
- else if (unformat (i, "new_local_cookie %lld", &new_local_cookie))
- ;
- else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie))
- ;
- else
- break;
- }
-
- if (sw_if_index_set == 0)