63 #define foreach_sr_policy_rewrite_next \ 64 _(IP6_LOOKUP, "ip6-lookup") \ 65 _(ERROR, "error-drop") 69 #define _(s,n) SR_POLICY_REWRITE_NEXT_##s, 76 #define foreach_sr_policy_rewrite_error \ 77 _(INTERNAL_ERROR, "Segment Routing undefined error") \ 78 _(BSID_ZERO, "BSID with SL = 0") \ 79 _(COUNTER_TOTAL, "SR steered IPv6 packets") \ 80 _(COUNTER_ENCAP, "SR: Encaps packets") \ 81 _(COUNTER_INSERT, "SR: SRH inserted packets") \ 82 _(COUNTER_BSID, "SR: BindingSID steered packets") 86 #define _(sym,str) SR_POLICY_REWRITE_ERROR_##sym, 93 #define _(sym,string) string, 145 .path =
"set sr encaps source",
146 .short_help =
"set sr encaps source addr <ip6_addr>",
173 if (!
unformat (input,
"%d", &hop_limit))
175 if (hop_limit <= 0 || hop_limit > 255)
183 .path =
"set sr encaps hop-limit",
184 .short_help =
"set sr encaps hop-limit <value>",
202 ip6_address_t *addrp, *this_address;
203 u32 header_length = 0;
211 header_length +=
vec_len (sl) *
sizeof (ip6_address_t);
218 clib_host_to_net_u32 (0 | ((6 & 0xF) << 28));
228 iph->
protocol = IP_PROTOCOL_IPV6_ROUTE;
234 (
vec_len (sl) *
sizeof (ip6_address_t))) / 8) - 1;
241 sizeof (ip6_address_t));
261 ip6_address_t *addrp, *this_address;
262 u32 header_length = 0;
267 header_length += (
vec_len (sl) + 1) *
sizeof (ip6_address_t);
276 ((
vec_len (sl) + 1) *
sizeof (ip6_address_t))) / 8) - 1;
283 sizeof (ip6_address_t));
300 ip6_address_t *addrp, *this_address;
301 u32 header_length = 0;
306 header_length +=
vec_len (sl) *
sizeof (ip6_address_t);
315 (
vec_len (sl) *
sizeof (ip6_address_t))) / 8) - 1;
322 sizeof (ip6_address_t));
352 clib_memset (segment_list, 0,
sizeof (*segment_list));
460 .ip6 = sr_policy->
bsid,
563 .ip6 = sr_policy->
bsid,
637 u16 plugin,
void *ls_plugin_mem)
665 (fib_table != (
u32) ~ 0 ? fib_table : 0));
678 sr_policy->
type = behavior;
679 sr_policy->
fib_table = (fib_table != (
u32) ~ 0 ? fib_table : 0);
684 sr_policy->
plugin = plugin;
693 create_sl (sr_policy, segments, weight, is_encap);
700 "SRv6 steering of IP6 prefixes through BSIDs");
703 "SRv6 steering of IP4 prefixes through BSIDs");
751 .ip6 = sr_policy->
bsid,
838 u32 *sl_index_iterate;
868 else if (operation == 2)
876 if (*sl_index_iterate == sl_index)
879 if (*sl_index_iterate != sl_index)
898 else if (operation == 3)
902 if (*sl_index_iterate == sl_index)
905 if (*sl_index_iterate != sl_index)
931 char is_del = 0, is_add = 0, is_mod = 0;
933 ip6_address_t bsid, next_address;
936 ip6_address_t *segments = 0, *this_seg;
941 void *ls_plugin_mem = 0;
945 if (!is_add && !is_mod && !is_del &&
unformat (input,
"add"))
947 else if (!is_add && !is_mod && !is_del &&
unformat (input,
"del"))
949 else if (!is_add && !is_mod && !is_del &&
unformat (input,
"mod"))
954 else if (!is_add && !policy_set
955 &&
unformat (input,
"index %d", &sr_policy_index))
957 else if (
unformat (input,
"weight %d", &weight));
965 else if (
unformat (input,
"add sl"))
971 else if (fib_table == (
u32) ~ 0
972 &&
unformat (input,
"fib-table %d", &fib_table));
975 else if (
unformat (input,
"insert"))
979 else if (!behavior &&
unformat (input,
"behavior"))
994 (input,
"%U", (*plugin_it)->ls_unformat, &ls_plugin_mem))
996 behavior = (*plugin_it)->sr_policy_function_number;
1010 if (!is_add && !is_mod && !is_del)
1018 if (behavior &&
vec_len (segments) == 0)
1030 behavior, ls_plugin_mem);
1043 if (operation == 1 &&
vec_len (segments) == 0)
1045 if (operation == 3 && weight == (
u32) ~ 0)
1049 sr_policy_index, fib_table, operation, segments,
1064 "There is already a FIB entry for the BindingSID address.\n" 1065 "The SR policy could not be created.");
1070 "The selected SR policy only contains ONE segment list. " 1071 "Please remove the SR policy instead");
1074 "Could not delete the segment list. " 1075 "It is not associated with that SR policy.");
1078 "Could not modify the segment list. " 1079 "The given SL is not associated with such SR policy.");
1088 .path =
"sr policy",
1089 .short_help =
"sr policy [add||del||mod] [bsid 2001::1||index 5] " 1090 "next A:: next B:: next C:: (weight 1) (fib-table 2) (encap|insert)",
1092 "Manipulation of SR policies.\n" 1093 "A Segment Routing policy may contain several SID lists. Each SID list has\n" 1094 "an associated weight (default 1), which will result in wECMP (uECMP).\n" 1095 "Segment Routing policies might be of type encapsulation or srh insertion\n" 1096 "Each SR policy will be associated with a unique BindingSID.\n" 1097 "A BindingSID is a locally allocated SegmentID. For every packet that arrives\n" 1098 "with IPv6_DA:BSID such traffic will be steered into the SR policy.\n" 1099 "The add command will create a SR policy with its first segment list (sl)\n" 1100 "The mod command allows you to add, remove, or modify the existing segment lists\n" 1101 "within an SR policy.\n" 1102 "The del command allows you to delete a SR policy along with all its associated\n" 1120 ip6_address_t *
addr;
1128 {
vec_add1 (vec_policies, sr_policy); }
1133 sr_policy = vec_policies[
i];
1138 (sr_policy->
is_encap ?
"Encapsulation" :
1150 s =
format (s,
"\t[%u].- ", *sl_index);
1157 s =
format (s,
"\b\b > ");
1168 .path =
"show sr policies",
1169 .short_help =
"show sr policies",
1189 .path =
"show sr encaps source addr",
1190 .short_help =
"show sr encaps source addr",
1210 .path =
"show sr encaps hop-limit",
1211 .short_help =
"show sr encaps hop-limit",
1229 (s,
"SR-policy-rewrite: src %U dst %U",
1255 (clib_net_to_host_u32 (
1258 (flow_label & 0x0000ffff));
1276 int encap_pkts = 0, bsid_pkts = 0;
1278 while (n_left_from > 0)
1285 while (n_left_from >= 8 && n_left_to_next >= 4)
1287 u32 bi0, bi1, bi2, bi3;
1289 u32 next0, next1, next2, next3;
1290 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1292 ip6_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
1316 to_next[0] = bi0 = from[0];
1317 to_next[1] = bi1 = from[1];
1318 to_next[2] = bi2 = from[2];
1319 to_next[3] = bi3 = from[3];
1323 n_left_to_next -= 4;
1393 sizeof (tr->
src.as_u8));
1395 sizeof (tr->
dst.as_u8));
1403 sizeof (tr->
src.as_u8));
1405 sizeof (tr->
dst.as_u8));
1413 sizeof (tr->
src.as_u8));
1415 sizeof (tr->
dst.as_u8));
1423 sizeof (tr->
src.as_u8));
1425 sizeof (tr->
dst.as_u8));
1431 n_left_to_next, bi0, bi1, bi2, bi3,
1432 next0, next1, next2, next3);
1436 while (n_left_from > 0 && n_left_to_next > 0)
1442 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1449 n_left_to_next -= 1;
1476 sizeof (tr->
src.as_u8));
1478 sizeof (tr->
dst.as_u8));
1483 n_left_to_next, bi0, next0);
1491 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
1494 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
1503 .name =
"sr-pl-rewrite-encaps",
1504 .vector_size =
sizeof (
u32),
1511 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 1533 ip0_encap->
ttl -= 1;
1534 checksum0 = ip0_encap->
checksum + clib_host_to_net_u16 (0x0100);
1535 checksum0 += checksum0 >= 0xffff;
1543 0 | ((6 & 0xF) << 28) | ((ip0_encap->
tos & 0xFF) << 20) |
1544 (flow_label & 0x0000ffff));
1545 if (ip0->
protocol == IP_PROTOCOL_IPV6_ROUTE)
1547 sr0 = (
void *) (ip0 + 1);
1548 sr0->
protocol = IP_PROTOCOL_IP_IN_IP;
1551 ip0->
protocol = IP_PROTOCOL_IP_IN_IP;
1569 int encap_pkts = 0, bsid_pkts = 0;
1571 while (n_left_from > 0)
1578 while (n_left_from >= 8 && n_left_to_next >= 4)
1580 u32 bi0, bi1, bi2, bi3;
1582 u32 next0, next1, next2, next3;
1583 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1585 ip4_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
1609 to_next[0] = bi0 = from[0];
1610 to_next[1] = bi1 = from[1];
1611 to_next[2] = bi2 = from[2];
1612 to_next[3] = bi3 = from[3];
1616 n_left_to_next -= 4;
1685 sizeof (tr->
src.as_u8));
1687 sizeof (tr->
dst.as_u8));
1695 sizeof (tr->
src.as_u8));
1697 sizeof (tr->
dst.as_u8));
1705 sizeof (tr->
src.as_u8));
1707 sizeof (tr->
dst.as_u8));
1715 sizeof (tr->
src.as_u8));
1717 sizeof (tr->
dst.as_u8));
1723 n_left_to_next, bi0, bi1, bi2, bi3,
1724 next0, next1, next2, next3);
1728 while (n_left_from > 0 && n_left_to_next > 0)
1735 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1742 n_left_to_next -= 1;
1769 sizeof (tr->
src.as_u8));
1771 sizeof (tr->
dst.as_u8));
1776 n_left_to_next, bi0, next0);
1784 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
1787 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
1796 .name =
"sr-pl-rewrite-encaps-v4",
1797 .vector_size =
sizeof (
u32),
1804 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 1825 return (*((
u64 *) m) & 0xffffffffffff);
1833 uword is_ip, eh_size;
1837 eh_type = clib_net_to_host_u16 (eh->
type);
1840 is_ip = (eh_type == ETHERNET_TYPE_IP4 || eh_type == ETHERNET_TYPE_IP6);
1870 int encap_pkts = 0, bsid_pkts = 0;
1872 while (n_left_from > 0)
1879 while (n_left_from >= 8 && n_left_to_next >= 4)
1881 u32 bi0, bi1, bi2, bi3;
1883 u32 next0, next1, next2, next3;
1884 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
1890 u32 flow_label0, flow_label1, flow_label2, flow_label3;
1913 to_next[0] = bi0 = from[0];
1914 to_next[1] = bi1 = from[1];
1915 to_next[2] = bi2 = from[2];
1916 to_next[3] = bi3 = from[3];
1920 n_left_to_next -= 4;
2046 if (ip0->
protocol == IP_PROTOCOL_IPV6_ROUTE)
2048 sr0 = (
void *) (ip0 + 1);
2054 if (ip1->
protocol == IP_PROTOCOL_IPV6_ROUTE)
2056 sr1 = (
void *) (ip1 + 1);
2062 if (ip2->
protocol == IP_PROTOCOL_IPV6_ROUTE)
2064 sr2 = (
void *) (ip2 + 1);
2070 if (ip3->
protocol == IP_PROTOCOL_IPV6_ROUTE)
2072 sr3 = (
void *) (ip3 + 1);
2081 0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
2083 0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label1 & 0xffff));
2085 0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label2 & 0xffff));
2087 0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label3 & 0xffff));
2096 sizeof (tr->
src.as_u8));
2098 sizeof (tr->
dst.as_u8));
2106 sizeof (tr->
src.as_u8));
2108 sizeof (tr->
dst.as_u8));
2116 sizeof (tr->
src.as_u8));
2118 sizeof (tr->
dst.as_u8));
2126 sizeof (tr->
src.as_u8));
2128 sizeof (tr->
dst.as_u8));
2134 n_left_to_next, bi0, bi1, bi2, bi3,
2135 next0, next1, next2, next3);
2139 while (n_left_from > 0 && n_left_to_next > 0)
2148 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2156 n_left_to_next -= 1;
2194 if (ip0->
protocol == IP_PROTOCOL_IPV6_ROUTE)
2196 sr0 = (
void *) (ip0 + 1);
2203 0 | ((6 & 0xF) << 28) | ((0x00) << 20) | (flow_label0 & 0xffff));
2211 sizeof (tr->
src.as_u8));
2213 sizeof (tr->
dst.as_u8));
2218 n_left_to_next, bi0, next0);
2226 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
2229 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
2238 .name =
"sr-pl-rewrite-encaps-l2",
2239 .vector_size =
sizeof (
u32),
2246 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 2268 int insert_pkts = 0, bsid_pkts = 0;
2270 while (n_left_from > 0)
2277 while (n_left_from >= 8 && n_left_to_next >= 4)
2279 u32 bi0, bi1, bi2, bi3;
2281 u32 next0, next1, next2, next3;
2282 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2286 u16 new_l0, new_l1, new_l2, new_l3;
2309 to_next[0] = bi0 = from[0];
2310 to_next[1] = bi1 = from[1];
2311 to_next[2] = bi2 = from[2];
2312 to_next[3] = bi3 = from[3];
2316 n_left_to_next -= 4;
2349 if (ip0->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2356 if (ip1->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2363 if (ip2->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2370 if (ip3->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2378 (
void *) sr0 - (
void *) ip0);
2380 (
void *) sr1 - (
void *) ip1);
2382 (
void *) sr2 - (
void *) ip2);
2384 (
void *) sr3 - (
void *) ip3);
2405 ip0->hop_limit -= 1;
2406 ip1->hop_limit -= 1;
2407 ip2->hop_limit -= 1;
2408 ip3->hop_limit -= 1;
2411 clib_net_to_host_u16 (ip0->payload_length) +
2414 clib_net_to_host_u16 (ip1->payload_length) +
2417 clib_net_to_host_u16 (ip2->payload_length) +
2420 clib_net_to_host_u16 (ip3->payload_length) +
2423 ip0->payload_length = clib_host_to_net_u16 (new_l0);
2424 ip1->payload_length = clib_host_to_net_u16 (new_l1);
2425 ip2->payload_length = clib_host_to_net_u16 (new_l2);
2426 ip3->payload_length = clib_host_to_net_u16 (new_l3);
2433 sr0->
segments->as_u64[0] = ip0->dst_address.as_u64[0];
2434 sr0->
segments->as_u64[1] = ip0->dst_address.as_u64[1];
2435 sr1->
segments->as_u64[0] = ip1->dst_address.as_u64[0];
2436 sr1->
segments->as_u64[1] = ip1->dst_address.as_u64[1];
2437 sr2->
segments->as_u64[0] = ip2->dst_address.as_u64[0];
2438 sr2->
segments->as_u64[1] = ip2->dst_address.as_u64[1];
2439 sr3->
segments->as_u64[0] = ip3->dst_address.as_u64[0];
2440 sr3->
segments->as_u64[1] = ip3->dst_address.as_u64[1];
2442 ip0->dst_address.as_u64[0] =
2444 ip0->dst_address.as_u64[1] =
2446 ip1->dst_address.as_u64[0] =
2448 ip1->dst_address.as_u64[1] =
2450 ip2->dst_address.as_u64[0] =
2452 ip2->dst_address.as_u64[1] =
2454 ip3->dst_address.as_u64[0] =
2456 ip3->dst_address.as_u64[1] =
2459 ip6_ext_header_t *ip_ext;
2460 if (ip0 + 1 == (
void *) sr0)
2463 ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2467 ip_ext = (
void *) (ip0 + 1);
2469 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2472 if (ip1 + 1 == (
void *) sr1)
2475 ip1->protocol = IP_PROTOCOL_IPV6_ROUTE;
2479 ip_ext = (
void *) (ip2 + 1);
2481 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2484 if (ip2 + 1 == (
void *) sr2)
2487 ip2->protocol = IP_PROTOCOL_IPV6_ROUTE;
2491 ip_ext = (
void *) (ip2 + 1);
2493 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2496 if (ip3 + 1 == (
void *) sr3)
2499 ip3->protocol = IP_PROTOCOL_IPV6_ROUTE;
2503 ip_ext = (
void *) (ip3 + 1);
2505 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2517 sizeof (tr->
src.as_u8));
2519 sizeof (tr->
dst.as_u8));
2527 sizeof (tr->
src.as_u8));
2529 sizeof (tr->
dst.as_u8));
2537 sizeof (tr->
src.as_u8));
2539 sizeof (tr->
dst.as_u8));
2547 sizeof (tr->
src.as_u8));
2549 sizeof (tr->
dst.as_u8));
2554 n_left_to_next, bi0, bi1, bi2, bi3,
2555 next0, next1, next2, next3);
2559 while (n_left_from > 0 && n_left_to_next > 0)
2566 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2574 n_left_to_next -= 1;
2585 if (ip0->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2593 (
void *) sr0 - (
void *) ip0);
2600 ip0->hop_limit -= 1;
2602 clib_net_to_host_u16 (ip0->payload_length) +
2604 ip0->payload_length = clib_host_to_net_u16 (new_l0);
2607 sr0->
segments->as_u64[0] = ip0->dst_address.as_u64[0];
2608 sr0->
segments->as_u64[1] = ip0->dst_address.as_u64[1];
2610 ip0->dst_address.as_u64[0] =
2612 ip0->dst_address.as_u64[1] =
2615 if (ip0 + 1 == (
void *) sr0)
2618 ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2622 ip6_ext_header_t *ip_ext = (
void *) (ip0 + 1);
2624 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2633 sizeof (tr->
src.as_u8));
2635 sizeof (tr->
dst.as_u8));
2641 n_left_to_next, bi0, next0);
2649 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
2652 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
2660 .name =
"sr-pl-rewrite-insert",
2661 .vector_size =
sizeof (
u32),
2668 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 2690 int insert_pkts = 0, bsid_pkts = 0;
2692 while (n_left_from > 0)
2699 while (n_left_from >= 8 && n_left_to_next >= 4)
2701 u32 bi0, bi1, bi2, bi3;
2703 u32 next0, next1, next2, next3;
2704 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2708 u16 new_l0, new_l1, new_l2, new_l3;
2731 to_next[0] = bi0 = from[0];
2732 to_next[1] = bi1 = from[1];
2733 to_next[2] = bi2 = from[2];
2734 to_next[3] = bi3 = from[3];
2738 n_left_to_next -= 4;
2771 if (ip0->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2778 if (ip1->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2785 if (ip2->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2792 if (ip3->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
2800 (
u8 *) ip0, (
void *) sr0 - (
void *) ip0);
2802 (
u8 *) ip1, (
void *) sr1 - (
void *) ip1);
2804 (
u8 *) ip2, (
void *) sr2 - (
void *) ip2);
2806 (
u8 *) ip3, (
void *) sr3 - (
void *) ip3);
2827 ip0->hop_limit -= 1;
2828 ip1->hop_limit -= 1;
2829 ip2->hop_limit -= 1;
2830 ip3->hop_limit -= 1;
2833 clib_net_to_host_u16 (ip0->payload_length) +
2836 clib_net_to_host_u16 (ip1->payload_length) +
2839 clib_net_to_host_u16 (ip2->payload_length) +
2842 clib_net_to_host_u16 (ip3->payload_length) +
2845 ip0->payload_length = clib_host_to_net_u16 (new_l0);
2846 ip1->payload_length = clib_host_to_net_u16 (new_l1);
2847 ip2->payload_length = clib_host_to_net_u16 (new_l2);
2848 ip3->payload_length = clib_host_to_net_u16 (new_l3);
2855 ip0->dst_address.as_u64[0] =
2857 ip0->dst_address.as_u64[1] =
2859 ip1->dst_address.as_u64[0] =
2861 ip1->dst_address.as_u64[1] =
2863 ip2->dst_address.as_u64[0] =
2865 ip2->dst_address.as_u64[1] =
2867 ip3->dst_address.as_u64[0] =
2869 ip3->dst_address.as_u64[1] =
2872 ip6_ext_header_t *ip_ext;
2873 if (ip0 + 1 == (
void *) sr0)
2876 ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
2880 ip_ext = (
void *) (ip0 + 1);
2882 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2885 if (ip1 + 1 == (
void *) sr1)
2888 ip1->protocol = IP_PROTOCOL_IPV6_ROUTE;
2892 ip_ext = (
void *) (ip2 + 1);
2894 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2897 if (ip2 + 1 == (
void *) sr2)
2900 ip2->protocol = IP_PROTOCOL_IPV6_ROUTE;
2904 ip_ext = (
void *) (ip2 + 1);
2906 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2909 if (ip3 + 1 == (
void *) sr3)
2912 ip3->protocol = IP_PROTOCOL_IPV6_ROUTE;
2916 ip_ext = (
void *) (ip3 + 1);
2918 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
2930 sizeof (tr->
src.as_u8));
2932 sizeof (tr->
dst.as_u8));
2940 sizeof (tr->
src.as_u8));
2942 sizeof (tr->
dst.as_u8));
2950 sizeof (tr->
src.as_u8));
2952 sizeof (tr->
dst.as_u8));
2960 sizeof (tr->
src.as_u8));
2962 sizeof (tr->
dst.as_u8));
2967 n_left_to_next, bi0, bi1, bi2, bi3,
2968 next0, next1, next2, next3);
2972 while (n_left_from > 0 && n_left_to_next > 0)
2979 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
2987 n_left_to_next -= 1;
2998 if (ip0->
protocol == IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
3006 (
u8 *) ip0, (
void *) sr0 - (
void *) ip0);
3013 ip0->hop_limit -= 1;
3015 clib_net_to_host_u16 (ip0->payload_length) +
3017 ip0->payload_length = clib_host_to_net_u16 (new_l0);
3021 ip0->dst_address.as_u64[0] =
3023 ip0->dst_address.as_u64[1] =
3026 if (ip0 + 1 == (
void *) sr0)
3029 ip0->protocol = IP_PROTOCOL_IPV6_ROUTE;
3033 ip6_ext_header_t *ip_ext = (
void *) (ip0 + 1);
3035 ip_ext->next_hdr = IP_PROTOCOL_IPV6_ROUTE;
3044 sizeof (tr->
src.as_u8));
3046 sizeof (tr->
dst.as_u8));
3052 n_left_to_next, bi0, next0);
3060 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
3063 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
3071 .name =
"sr-pl-rewrite-b-insert",
3072 .vector_size =
sizeof (
u32),
3079 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 3095 ip6_address_t *new_dst0;
3098 goto error_bsid_encaps;
3105 new_dst0 = (ip6_address_t *) (sr0->
segments);
3114 *next0 = SR_POLICY_REWRITE_NEXT_ERROR;
3115 b0->
error = node->
errors[SR_POLICY_REWRITE_ERROR_BSID_ZERO];
3133 int encap_pkts = 0, bsid_pkts = 0;
3135 while (n_left_from > 0)
3142 while (n_left_from >= 8 && n_left_to_next >= 4)
3144 u32 bi0, bi1, bi2, bi3;
3146 u32 next0, next1, next2, next3;
3147 next0 = next1 = next2 = next3 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
3149 ip6_header_t *ip0_encap, *ip1_encap, *ip2_encap, *ip3_encap;
3174 to_next[0] = bi0 = from[0];
3175 to_next[1] = bi1 = from[1];
3176 to_next[2] = bi2 = from[2];
3177 to_next[3] = bi3 = from[3];
3181 n_left_to_next -= 4;
3263 sizeof (tr->
src.as_u8));
3265 sizeof (tr->
dst.as_u8));
3273 sizeof (tr->
src.as_u8));
3275 sizeof (tr->
dst.as_u8));
3283 sizeof (tr->
src.as_u8));
3285 sizeof (tr->
dst.as_u8));
3293 sizeof (tr->
src.as_u8));
3295 sizeof (tr->
dst.as_u8));
3301 n_left_to_next, bi0, bi1, bi2, bi3,
3302 next0, next1, next2, next3);
3306 while (n_left_from > 0 && n_left_to_next > 0)
3313 u32 next0 = SR_POLICY_REWRITE_NEXT_IP6_LOOKUP;
3320 n_left_to_next -= 1;
3349 sizeof (tr->
src.as_u8));
3351 sizeof (tr->
dst.as_u8));
3356 n_left_to_next, bi0, next0);
3364 SR_POLICY_REWRITE_ERROR_COUNTER_TOTAL,
3367 SR_POLICY_REWRITE_ERROR_COUNTER_BSID,
3376 .name =
"sr-pl-rewrite-b-encaps",
3377 .vector_size =
sizeof (
u32),
3384 #define _(s,n) [SR_POLICY_REWRITE_NEXT_##s] = n, 3455 vlib_cli_output (vm,
"SR Policy behaviors:\n-----------------------\n\n");
3459 {
vec_add1 (plugins_vec, plugin); }
3463 for (i = 0; i <
vec_len (plugins_vec); i++)
3465 plugin = plugins_vec[
i];
3475 .path =
"show sr policy behaviors",
3476 .short_help =
"show sr policy behaviors",
3486 ip6_address_t *
addr;
3491 s =
format (s,
"SR: Segment List index:[%d]", index);
3492 s =
format (s,
"\n\tSegments:");
3501 s =
format (s,
"\b\b > - ");
3514 "sr-pl-rewrite-encaps",
3519 "sr-pl-rewrite-encaps-v4",
3529 "sr-pl-rewrite-insert",
3538 "sr-pl-rewrite-b-insert",
3547 "sr-pl-rewrite-b-encaps",
3566 sizeof (ip6_address_t));
u8 * params_str
Behavior parameters (i.e.
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
static clib_error_t * sr_policy_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI for 'sr policies' command family.
static u8 * compute_rewrite_insert(ip6_address_t *sl)
SR rewrite string computation for SRH insertion (inline)
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
fib_protocol_t fp_proto
protocol type
dpo_lock_fn_t dv_lock
A reference counting lock function.
u8 type
Type (default is 0)
#define vec_foreach_index(var, v)
Iterate over vector indices.
static clib_error_t * show_sr_policy_behaviors_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI function to 'show' all available SR LocalSID behaviors.
fib_node_index_t path_index
The index of the FIB path.
#define foreach_sr_policy_rewrite_error
A virtual function table regisitered for a DPO type.
static uword sr_policy_rewrite_b_insert(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a packet.
#define IP_PROTOCOL_IP6_ETHERNET
int sr_policy_add(ip6_address_t *bsid, ip6_address_t *segments, u32 weight, u8 behavior, u32 fib_table, u8 is_encap, u16 plugin, void *ls_plugin_mem)
Create a new SR policy.
uword * policy_plugin_functions_by_key
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
dpo_id_t path_dpo
ID of the Data-path object.
vlib_main_t vlib_node_runtime_t vlib_frame_t * from_frame
#define pool_foreach(VAR, POOL)
Iterate through pool.
format_function_t * ls_format
LocalSID format function.
static uword sr_policy_rewrite_b_encaps(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy BSID - Encapsulation.
sr_p_plugin_callback_t * removal
Function within plugin that will be called before localsid removal.
void sr_dpo_unlock(dpo_id_t *dpo)
no-op unlock function.
static const char *const sr_pr_encaps_ip4_nodes[]
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
vlib_node_registration_t sr_policy_rewrite_b_encaps_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_b_encaps_node)
static u32 ip4_compute_flow_hash(const ip4_header_t *ip, flow_hash_config_t flow_hash_config)
unsigned char params_str[32]
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
#define ethernet_buffer_header_size(b)
Determine the size of the Ethernet headers of the current frame in the buffer.
int sr_policy_mod(ip6_address_t *bsid, u32 index, u32 fib_table, u8 operation, ip6_address_t *segments, u32 sl_index, u32 weight)
Modify an existing SR policy.
dpo_id_t ip4_dpo
DPO for Encaps IPv6.
#define VLIB_BUFFER_PRE_DATA_SIZE
static uword sr_policy_rewrite_insert(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a packet.
u16 current_length
Nbytes between current data and the end of this buffer.
ip6_address_t * segments
SIDs (key)
static u8 * compute_rewrite_bsid(ip6_address_t *sl)
SR rewrite string computation for SRH insertion with BSID (inline)
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
#define vlib_validate_buffer_enqueue_x4(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, bi2, bi3, next0, next1, next2, next3)
Finish enqueueing four buffers forward in the graph.
static clib_error_t * set_sr_src_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
dpo_type_t dpo
DPO type registration.
static ip6_sr_sl_t * create_sl(ip6_sr_policy_t *sr_policy, ip6_address_t *sl, u32 weight, u8 is_encap)
Creates a Segment List and adds it to an SR policy.
#define hash_set_mem(h, key, value)
static const char *const *const sr_pr_bsid_encaps_nodes[DPO_PROTO_NUM]
#define IPv6_DEFAULT_HEADER_LENGTH
u32 l2_sr_policy_rewrite_index
#define ROUTING_HEADER_TYPE_SR
unsigned char keyword_str[32]
static u8 * format_sr_segment_list_dpo(u8 *s, va_list *args)
vlib_error_t * errors
Vector of errors for this node.
int sr_policy_register_function(vlib_main_t *vm, u8 *fn_name, u8 *keyword_str, u8 *def_str, u8 *params_str, u8 prefix_length, dpo_type_t *dpo, format_function_t *ls_format, unformat_function_t *ls_unformat, sr_p_plugin_callback_t *creation_fn, sr_p_plugin_callback_t *removal_fn)
SR Policy plugin registry.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
ip6_sr_steering_policy_t * steer_policies
static_always_inline void encaps_processing_v6(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip6_header_t *ip0_encap)
IPv6 encapsulation processing as per RFC2473.
vlib_node_registration_t sr_policy_rewrite_encaps_v4_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_v4_node)
u8 * rewrite_bsid
Precomputed rewrite header for bindingSID.
void sr_set_hop_limit(u8 hop_limit)
vlib_node_registration_t sr_policy_rewrite_encaps_l2_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_l2_node)
static uword sr_policy_rewrite_encaps_l2(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into a L2 frame.
u16 sr_policy_function_number
SR Policy plugin function.
flow_hash_config_t fib_table_get_flow_hash_config(u32 fib_index, fib_protocol_t proto)
Get the flow hash configured used by the table.
#define clib_memcpy(d, s, n)
index_t load_balance_create(u32 n_buckets, dpo_proto_t lb_proto, flow_hash_config_t fhc)
dpo_id_t ip6_dpo
DPO for Encaps/Insert IPv6.
u32 * sw_iface_sr_policies
vlib_node_registration_t sr_policy_rewrite_encaps_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_encaps_node)
#define static_always_inline
enum dpo_type_t_ dpo_type_t
Common types of data-path objects New types can be dynamically added using dpo_register_new_type() ...
static const char *const sr_pr_insert_ip6_nodes[]
static u32 l2_flow_hash(vlib_buffer_t *b0)
#define VLIB_INIT_FUNCTION(x)
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a 'special' entry from the FIB.
sr_policy_fn_registration_t * policy_plugin_functions
SR Segment List (SID list)
description fragment has unexpected format
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
Aggregate type for a prefix.
#define clib_error_return(e, args...)
sr_p_plugin_callback_t * creation
Function within plugin that will be called after localsid creation.
void load_balance_multipath_update(const dpo_id_t *dpo, const load_balance_path_t *raw_nhs, load_balance_flags_t flags)
static uword sr_policy_rewrite_encaps(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into an IPv6 packet.
static const char *const *const sr_pr_encaps_nodes[DPO_PROTO_NUM]
static u64 mac_to_u64(u8 *m)
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
SR Policy behavior registration.
dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char *const *const *nodes)
Create and register a new DPO type.
static void * ip6_ext_header_find(vlib_main_t *vm, vlib_buffer_t *b, ip6_header_t *ip6_header, u8 header_type, ip6_ext_header_t **prev_ext_header)
int sr_policy_del(ip6_address_t *bsid, u32 index)
Delete a SR policy.
#define SR_POLICY_TYPE_DEFAULT
vl_api_fib_path_type_t type
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static void update_replicate(ip6_sr_policy_t *sr_policy)
Updates the Replicate DPO after an SR Policy change.
vlib_node_registration_t sr_policy_rewrite_b_insert_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_b_insert_node)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
vl_api_interface_index_t sw_if_index
enum flow_hash_config_t_ flow_hash_config_t
A flow hash configuration is a mask of the flow hash options.
vlib_node_registration_t sr_policy_rewrite_insert_node
(constructor) VLIB_REGISTER_NODE (sr_policy_rewrite_insert_node)
static const char *const sr_pr_bsid_insert_ip6_nodes[]
void sr_set_source(ip6_address_t *address)
static u32 ip6_fib_index_from_table_id(u32 table_id)
static dpo_type_t sr_pr_bsid_insert_dpo_type
unsigned char def_str[64]
static u8 * compute_rewrite_encaps(ip6_address_t *sl)
SR rewrite string computation for IPv6 encapsulation (inline)
load-balancing over a choice of [un]equal cost paths
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
#define pool_put(P, E)
Free an object E in pool P.
#define vec_dup(V)
Return copy of vector (no header, no alignment)
void sr_dpo_lock(dpo_id_t *dpo)
no-op lock function.
#define vec_del1(v, i)
Delete the element at index I.
vlib_main_t * vm
X-connect all packets from the HOST to the PHY.
#define IP_FLOW_HASH_DEFAULT
Default: 5-tuple + flowlabel without the "reverse" bit.
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
static uword mhash_set(mhash_t *h, void *key, uword new_value, uword *old_value)
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
void fib_table_unlock(u32 fib_index, fib_protocol_t proto, fib_source_t source)
Take a reference counting lock on the table.
static u8 sr_pr_encaps_hop_limit
u8 is_encap
Mode (0 is SRH insert, 1 Encaps)
static uword sr_policy_rewrite_encaps_v4(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *from_frame)
Graph node for applying a SR policy into an IPv4 packet.
u32 weight
SID list weight (wECMP / UCMP)
__clib_export void mhash_init(mhash_t *h, uword n_value_bytes, uword n_key_bytes)
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
sr_policy_rewrite_error_t
unformat_function_t * ls_unformat
LocalSID unformat function.
static clib_error_t * set_sr_hop_limit_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
#define ip6_ext_header_len(p)
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
void replicate_multipath_update(const dpo_id_t *dpo, load_balance_path_t *next_hops)
#define VLIB_REGISTER_NODE(x,...)
fib_node_index_t fib_table_entry_special_dpo_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Update a 'special' entry to the FIB that links to the DPO passed A special entry is an entry that the...
#define hash_mix64(a0, b0, c0)
#define CLIB_PREFETCH(addr, size, type)
static clib_error_t * show_sr_encaps_source_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen the SR encaps source addr.
sll srl srl sll sra u16x4 i
static const char *const sr_pr_bsid_encaps_ip6_nodes[]
#define vec_free(V)
Free vector's memory (no header).
static_always_inline void end_bsid_encaps_srh_processing(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip6_sr_header_t *sr0, u32 *next0)
Function BSID encapsulation.
static u8 * format_sr_policy_rewrite_trace(u8 *s, va_list *args)
Trace for the SR Policy Rewrite graph node.
u32 * segments_lists
SID lists indexes (vector)
u32 fib_node_index_t
A typedef of a node index.
dpo_id_t bsid_dpo
DPO for Encaps/Insert for BSID.
void dpo_set(dpo_id_t *dpo, dpo_type_t type, dpo_proto_t proto, index_t index)
Set/create a DPO ID The DPO will be locked.
index_t replicate_create(u32 n_buckets, dpo_proto_t rep_proto)
#define foreach_sr_policy_rewrite_next
u8 * function_name
Function name.
u32 egress_fib_table
Egress FIB table for encap packet.
clib_error_t * sr_policy_rewrite_init(vlib_main_t *vm)
SR Policy Rewrite initialization.
#define VLIB_CLI_COMMAND(x,...)
u8 * def_str
Behavior definition (i.e.
static const char *const *const sr_pr_bsid_insert_nodes[DPO_PROTO_NUM]
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
#define pool_put_index(p, i)
Free pool element with given index.
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
manual_print typedef address
static uword * mhash_get(mhash_t *h, const void *key)
static const char *const *const sr_pr_insert_nodes[DPO_PROTO_NUM]
#define SR_POLICY_TYPE_SPRAY
ip6_address_t * sr_get_encaps_source()
vlib_put_next_frame(vm, node, next_index, 0)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
static_always_inline void * clib_memcpy_fast(void *restrict dst, const void *restrict src, size_t n)
static dpo_type_t sr_pr_encaps_dpo_type
Dynamically added SR SL DPO type.
nat44_ei_hairpin_src_next_t next_index
static_always_inline void encaps_processing_v4(vlib_node_runtime_t *node, vlib_buffer_t *b0, ip6_header_t *ip0, ip4_header_t *ip0_encap)
IPv4 encapsulation processing as per RFC2473.
#define SR_SEGMENT_LIST_WEIGHT_DEFAULT
mhash_t sr_policies_index_hash
static u32 ip6_compute_flow_hash(const ip6_header_t *ip, flow_hash_config_t flow_hash_config)
__clib_export uword mhash_unset(mhash_t *h, void *key, uword *old_value)
#define FIB_NODE_INDEX_INVALID
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
ip6_sr_policy_t * sr_policies
vlib_main_t vlib_node_runtime_t * node
u32 path_weight
weight for the path.
u8 * rewrite
Precomputed rewrite header.
VLIB buffer representation.
int() sr_p_plugin_callback_t(ip6_sr_policy_t *sr)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
dpo_id_t bsid_dpo
SR Policy specific DPO - BSID.
static dpo_type_t sr_pr_insert_dpo_type
One path from an [EU]CMP set that the client wants to add to a load-balance object.
#define hash_get_mem(h, key)
static char * sr_policy_rewrite_error_strings[]
Segment Routing data structures definitions.
Segment Routing main datastructure.
static clib_error_t * show_sr_encaps_hop_limit_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen the hop-limit value used for SRv6 encapsulation.
dpo_id_t ip6_dpo
SR Policy specific DPO - IPv4.
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
#define vec_foreach(var, vec)
Vector iterator.
static const char *const sr_pr_encaps_ip6_nodes[]
u16 flags
Copy of main node flags.
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
static dpo_type_t sr_pr_bsid_encaps_dpo_type
#define VLIB_NODE_FLAG_TRACE
u8 sr_get_hop_limit(void)
#define CLIB_CACHE_LINE_BYTES
#define IPv6_DEFAULT_HOP_LIMIT
u32 fib_table_create_and_lock(fib_protocol_t proto, fib_source_t src, const char *const fmt,...)
Create a new table with no table ID.
dpo_id_t ip4_dpo
SR Policy specific DPO - IPv6.
static ip6_address_t sr_pr_encaps_src
IPv6 SA for encapsulated packets.
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static void update_lb(ip6_sr_policy_t *sr_policy)
Updates the Load Balancer after an SR Policy change.
ip6_address_t bsid
BindingSID (key)
static u32 ip_flow_hash(void *data)
static clib_error_t * show_sr_policies_command_fn(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
CLI to display onscreen all the SR policies.
u8 * keyword_str
Behavior keyword (i.e.
static uword pool_elts(void *v)
Number of active elements in a pool.