diff options
-rw-r--r-- | src/vnet/srv6/sr.h | 1 | ||||
-rw-r--r-- | src/vnet/srv6/sr_packet.h | 18 | ||||
-rw-r--r-- | src/vnet/srv6/sr_policy_rewrite.c | 71 |
3 files changed, 87 insertions, 3 deletions
diff --git a/src/vnet/srv6/sr.h b/src/vnet/srv6/sr.h index 507f8dfab9f..02cceade682 100644 --- a/src/vnet/srv6/sr.h +++ b/src/vnet/srv6/sr.h @@ -90,6 +90,7 @@ typedef struct /* SR policy types */ #define SR_POLICY_TYPE_DEFAULT 0 #define SR_POLICY_TYPE_SPRAY 1 +#define SR_POLICY_TYPE_TEF 2 /** * @brief SR Policy */ diff --git a/src/vnet/srv6/sr_packet.h b/src/vnet/srv6/sr_packet.h index dda776b4037..cf9fcb70bcc 100644 --- a/src/vnet/srv6/sr_packet.h +++ b/src/vnet/srv6/sr_packet.h @@ -116,6 +116,9 @@ #define ROUTING_HEADER_TYPE_SR 4 +#define IP6_SRH_PT_TLV_TYPE 128 +#define IP6_SRH_PT_TLV_LEN 14 + typedef struct { /* Protocol for next header. */ @@ -156,6 +159,21 @@ typedef struct u8 value[0]; } __attribute__ ((packed)) ip6_sr_tlv_t; +typedef struct +{ + u32 sec; + u32 nsec; +} __attribute__ ((packed)) timestamp_64_t; + +typedef struct +{ + u8 type; + u8 length; + u16 id_ld; + timestamp_64_t t64; + u16 session_id; + u16 seq_num; +} __attribute__ ((packed)) ip6_sr_pt_tlv_t; /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/srv6/sr_policy_rewrite.c b/src/vnet/srv6/sr_policy_rewrite.c index fdbf0dd08fa..0134f3c083b 100644 --- a/src/vnet/srv6/sr_policy_rewrite.c +++ b/src/vnet/srv6/sr_policy_rewrite.c @@ -199,13 +199,20 @@ compute_rewrite_encaps (ip6_address_t *sl, u8 type) { ip6_header_t *iph; ip6_sr_header_t *srh; + ip6_sr_pt_tlv_t *srh_pt_tlv; ip6_address_t *addrp, *this_address; u32 header_length = 0; u8 *rs = NULL; header_length = 0; header_length += IPv6_DEFAULT_HEADER_LENGTH; - if (vec_len (sl) > 1) + if (type == SR_POLICY_TYPE_TEF) + { + header_length += sizeof (ip6_sr_header_t); + header_length += vec_len (sl) * sizeof (ip6_address_t); + header_length += sizeof (ip6_sr_pt_tlv_t); + } + else if (vec_len (sl) > 1) { header_length += sizeof (ip6_sr_header_t); header_length += vec_len (sl) * sizeof (ip6_address_t); @@ -222,7 +229,33 @@ compute_rewrite_encaps (ip6_address_t *sl, u8 type) iph->protocol = IP_PROTOCOL_IPV6; iph->hop_limit = sr_pr_encaps_hop_limit; - if (vec_len (sl) > 1) + if (type == SR_POLICY_TYPE_TEF) + { + srh = (ip6_sr_header_t *) (iph + 1); + iph->protocol = IP_PROTOCOL_IPV6_ROUTE; + srh->protocol = IP_PROTOCOL_IPV6; + srh->type = ROUTING_HEADER_TYPE_SR; + srh->flags = 0x00; + srh->tag = 0x0000; + srh->segments_left = vec_len (sl) - 1; + srh->last_entry = vec_len (sl) - 1; + srh->length = + ((sizeof (ip6_sr_header_t) + (vec_len (sl) * sizeof (ip6_address_t)) + + sizeof (ip6_sr_pt_tlv_t)) / + 8) - + 1; + addrp = srh->segments + vec_len (sl) - 1; + vec_foreach (this_address, sl) + { + clib_memcpy_fast (addrp->as_u8, this_address->as_u8, + sizeof (ip6_address_t)); + addrp--; + } + srh_pt_tlv = (ip6_sr_pt_tlv_t *) (srh->segments + vec_len (sl)); + srh_pt_tlv->type = IP6_SRH_PT_TLV_TYPE; + srh_pt_tlv->length = IP6_SRH_PT_TLV_LEN; + } + else if (vec_len (sl) > 1) { srh = (ip6_sr_header_t *) (iph + 1); iph->protocol = IP_PROTOCOL_IPV6_ROUTE; @@ -705,7 +738,8 @@ sr_policy_add (ip6_address_t *bsid, ip6_address_t *segments, u32 weight, } /* Create IPv6 FIB for the BindingSID attached to the DPO of the only SL */ - if (sr_policy->type == SR_POLICY_TYPE_DEFAULT) + if (sr_policy->type == SR_POLICY_TYPE_DEFAULT || + sr_policy->type == SR_POLICY_TYPE_TEF) update_lb (sr_policy); else if (sr_policy->type == SR_POLICY_TYPE_SPRAY) update_replicate (sr_policy); @@ -973,6 +1007,8 @@ sr_policy_command_fn (vlib_main_t * vm, unformat_input_t * input, is_encap = 0; else if (unformat (input, "spray")) type = SR_POLICY_TYPE_SPRAY; + else if (unformat (input, "tef")) + type = SR_POLICY_TYPE_TEF; else if (!behavior && unformat (input, "behavior")) { sr_policy_fn_registration_t *plugin = 0, **vec_plugins = 0; @@ -1137,6 +1173,10 @@ show_sr_policies_command_fn (vlib_main_t * vm, unformat_input_t * input, case SR_POLICY_TYPE_SPRAY: vlib_cli_output (vm, "\tType: %s", "Spray"); break; + case SR_POLICY_TYPE_TEF: + vlib_cli_output (vm, "\tType: %s", + "TEF (Timestamp, Encapsulate, and Forward)"); + break; default: vlib_cli_output (vm, "\tType: %s", "Default"); break; @@ -1232,6 +1272,27 @@ format_sr_policy_rewrite_trace (u8 * s, va_list * args) return s; } +/** + * @brief SRv6 TEF (Timestamp, Encapsulate, and Forward) behavior + */ +static_always_inline void +srv6_tef_behavior (vlib_node_runtime_t *node, vlib_buffer_t *b0, + ip6_header_t *ip0) +{ + ip6_sr_header_t *srh; + ip6_sr_pt_tlv_t *srh_pt_tlv; + timestamp_64_t ts; + srh = (ip6_sr_header_t *) (ip0 + 1); + + srh_pt_tlv = + (ip6_sr_pt_tlv_t *) ((u8 *) ip0 + sizeof (ip6_header_t) + + sizeof (ip6_sr_header_t) + + sizeof (ip6_address_t) * (srh->last_entry + 1)); + + unix_time_now_nsec_fraction (&ts.sec, &ts.nsec); + srh_pt_tlv->t64.sec = htobe32 (ts.sec); + srh_pt_tlv->t64.nsec = htobe32 (ts.nsec); +} /** * @brief IPv6 encapsulation processing as per RFC2473 @@ -1257,6 +1318,8 @@ encaps_processing_v6 (vlib_node_runtime_t *node, vlib_buffer_t *b0, ip0_encap->ip_version_traffic_class_and_flow_label) & 0xfff00000) | (flow_label & 0x0000ffff)); + if (policy_type == SR_POLICY_TYPE_TEF) + srv6_tef_behavior (node, b0, ip0); } /** @@ -3108,6 +3171,8 @@ end_bsid_encaps_srh_processing (vlib_node_runtime_t *node, vlib_buffer_t *b0, ip0->dst_address.as_u64[1] = new_dst0->as_u64[1]; return; } + else if (sr0->segments_left == 0 && policy_type == SR_POLICY_TYPE_TEF) + return; } error_bsid_encaps: |