Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 1 | /* |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 2 | * Copyright (c) 2016 Cisco and/or its affiliates. |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
Ole Troan | 944f548 | 2016-05-24 11:56:58 +0200 | [diff] [blame] | 15 | #ifndef __included_ip6_hop_by_hop_ioam_h__ |
| 16 | #define __included_ip6_hop_by_hop_ioam_h__ |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 17 | |
| 18 | #include <vnet/ip/ip6_hop_by_hop_packet.h> |
Shwetha Bhandari | 05866a1 | 2016-05-04 08:12:57 +0200 | [diff] [blame] | 19 | #include <vnet/ip/ip.h> |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 20 | |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 21 | |
| 22 | #define MAX_IP6_HBH_OPTION 256 |
| 23 | |
| 24 | /* To determine whether a node is decap MS bit is set */ |
| 25 | #define IOAM_DECAP_BIT 0x80000000 |
| 26 | |
| 27 | #define IOAM_DEAP_ENABLED(opaque_data) (opaque_data & IOAM_DECAP_BIT) |
| 28 | |
| 29 | #define IOAM_SET_DECAP(opaque_data) \ |
| 30 | (opaque_data |= IOAM_DECAP_BIT) |
| 31 | |
| 32 | #define IOAM_MASK_DECAP_BIT(x) (x & ~IOAM_DECAP_BIT) |
| 33 | |
| 34 | /* |
| 35 | * Stores the run time flow data of hbh options |
| 36 | */ |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 37 | typedef struct |
| 38 | { |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 39 | u32 ctx[MAX_IP6_HBH_OPTION]; |
| 40 | u8 flow_name[64]; |
| 41 | } flow_data_t; |
| 42 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 43 | typedef struct |
| 44 | { |
Dave Barach | 9080096 | 2019-05-24 13:03:01 -0400 | [diff] [blame] | 45 | u8 next_index_by_protocol[256]; |
| 46 | } ip6_local_hop_by_hop_runtime_t; |
| 47 | |
| 48 | typedef struct |
| 49 | { |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 50 | /* The current rewrite we're using */ |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 51 | u8 *rewrite; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 52 | |
| 53 | /* Trace data processing callback */ |
| 54 | void *ioam_end_of_path_cb; |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 55 | /* Configuration data */ |
| 56 | /* Adjacency */ |
| 57 | ip6_address_t adj; |
| 58 | #define IOAM_HBYH_ADD 0 |
| 59 | #define IOAM_HBYH_MOD 1 |
| 60 | #define IOAM_HBYH_POP 2 |
| 61 | u8 ioam_flag; |
| 62 | /* time scale transform. Joy. */ |
| 63 | u32 unix_time_0; |
| 64 | f64 vlib_time_0; |
| 65 | |
| 66 | |
| 67 | /* Trace option */ |
Vengada Govindan | 07d2f84 | 2016-08-25 10:34:34 -0700 | [diff] [blame] | 68 | u8 has_trace_option; |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 69 | |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 70 | /* Pot option */ |
| 71 | u8 has_pot_option; |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 72 | |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 73 | /* Per Packet Counter option */ |
| 74 | u8 has_seqno_option; |
| 75 | |
| 76 | /* Enabling analyis of iOAM data on decap node */ |
| 77 | u8 has_analyse_option; |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 78 | |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 79 | /* Array of function pointers to ADD and POP HBH option handling routines */ |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 80 | u8 options_size[MAX_IP6_HBH_OPTION]; |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 81 | int (*add_options[MAX_IP6_HBH_OPTION]) (u8 * rewrite_string, |
| 82 | u8 * rewrite_size); |
| 83 | int (*pop_options[MAX_IP6_HBH_OPTION]) (vlib_buffer_t * b, |
| 84 | ip6_header_t * ip, |
| 85 | ip6_hop_by_hop_option_t * opt); |
| 86 | int (*get_sizeof_options[MAX_IP6_HBH_OPTION]) (u32 * rewrite_size); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 87 | int (*config_handler[MAX_IP6_HBH_OPTION]) (void *data, u8 disable); |
| 88 | |
| 89 | /* Array of function pointers to handle hbh options being used with classifier */ |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 90 | u32 (*flow_handler[MAX_IP6_HBH_OPTION]) (u32 flow_ctx, u8 add); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 91 | flow_data_t *flows; |
| 92 | |
Dave Barach | 9080096 | 2019-05-24 13:03:01 -0400 | [diff] [blame] | 93 | ip6_local_hop_by_hop_runtime_t *ip6_local_hbh_runtime; |
| 94 | |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 95 | /* convenience */ |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 96 | vlib_main_t *vlib_main; |
| 97 | vnet_main_t *vnet_main; |
Ole Troan | 944f548 | 2016-05-24 11:56:58 +0200 | [diff] [blame] | 98 | } ip6_hop_by_hop_ioam_main_t; |
Ed Warnicke | cb9cada | 2015-12-08 15:45:58 -0700 | [diff] [blame] | 99 | |
Ole Troan | 944f548 | 2016-05-24 11:56:58 +0200 | [diff] [blame] | 100 | extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main; |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 101 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 102 | extern clib_error_t *ip6_ioam_enable (int has_trace_option, |
| 103 | int has_pot_option, |
| 104 | int has_seqno_option, |
| 105 | int has_analyse_option); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 106 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 107 | extern int ip6_ioam_set_destination (ip6_address_t * addr, u32 mask_width, |
| 108 | u32 vrf_id, int is_add, int is_pop, |
| 109 | int is_none); |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 110 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 111 | extern clib_error_t *clear_ioam_rewrite_fn (void); |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 112 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 113 | static inline u8 |
| 114 | is_zero_ip4_address (ip4_address_t * a) |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 115 | { |
| 116 | return (a->as_u32 == 0); |
| 117 | } |
| 118 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 119 | static inline void |
| 120 | copy_ip6_address (ip6_address_t * dst, ip6_address_t * src) |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 121 | { |
| 122 | dst->as_u64[0] = src->as_u64[0]; |
| 123 | dst->as_u64[1] = src->as_u64[1]; |
| 124 | } |
| 125 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 126 | static inline void |
| 127 | set_zero_ip6_address (ip6_address_t * a) |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 128 | { |
| 129 | a->as_u64[0] = 0; |
| 130 | a->as_u64[1] = 0; |
| 131 | } |
| 132 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 133 | static inline u8 |
| 134 | cmp_ip6_address (ip6_address_t * a1, ip6_address_t * a2) |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 135 | { |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 136 | return ((a1->as_u64[0] == a2->as_u64[0]) |
| 137 | && (a1->as_u64[1] == a2->as_u64[1])); |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 138 | } |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 139 | |
| 140 | static inline u8 |
| 141 | is_zero_ip6_address (ip6_address_t * a) |
rangan | 4f81085 | 2016-03-18 03:31:17 +0530 | [diff] [blame] | 142 | { |
| 143 | return ((a->as_u64[0] == 0) && (a->as_u64[1] == 0)); |
| 144 | } |
| 145 | |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 146 | int ip6_hbh_add_register_option (u8 option, |
| 147 | u8 size, |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 148 | int rewrite_options (u8 * rewrite_string, |
| 149 | u8 * size)); |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 150 | int ip6_hbh_add_unregister_option (u8 option); |
| 151 | |
| 152 | int ip6_hbh_pop_register_option (u8 option, |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 153 | int options (vlib_buffer_t * b, |
| 154 | ip6_header_t * ip, |
| 155 | ip6_hop_by_hop_option_t * opt)); |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 156 | int ip6_hbh_pop_unregister_option (u8 option); |
| 157 | |
Vengada Govindan | 07d2f84 | 2016-08-25 10:34:34 -0700 | [diff] [blame] | 158 | int |
| 159 | ip6_hbh_get_sizeof_register_option (u8 option, |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 160 | int get_sizeof_hdr_options (u32 * |
| 161 | rewrite_size)); |
Shwetha | 85b528e | 2016-06-15 16:34:16 +0100 | [diff] [blame] | 162 | |
Vengada Govindan | 07d2f84 | 2016-08-25 10:34:34 -0700 | [diff] [blame] | 163 | int |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 164 | ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 165 | int has_pot_option, int has_seq_no); |
| 166 | |
| 167 | int |
| 168 | ip6_hbh_config_handler_register (u8 option, |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 169 | int config_handler (void *data, u8 disable)); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 170 | |
| 171 | int ip6_hbh_config_handler_unregister (u8 option); |
| 172 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 173 | int ip6_hbh_flow_handler_register (u8 option, |
| 174 | u32 ioam_flow_handler (u32 flow_ctx, |
| 175 | u8 add)); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 176 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 177 | int ip6_hbh_flow_handler_unregister (u8 option); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 178 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 179 | u8 *get_flow_name_from_flow_ctx (u32 flow_ctx); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 180 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 181 | static inline flow_data_t * |
| 182 | get_flow (u32 index) |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 183 | { |
| 184 | flow_data_t *flow = NULL; |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 185 | ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 186 | |
| 187 | if (pool_is_free_index (hm->flows, index)) |
| 188 | return NULL; |
| 189 | |
| 190 | flow = pool_elt_at_index (hm->flows, index); |
| 191 | return flow; |
| 192 | } |
| 193 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 194 | static inline u32 |
| 195 | get_flow_data_from_flow_ctx (u32 flow_ctx, u8 option) |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 196 | { |
| 197 | flow_data_t *flow = NULL; |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 198 | ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 199 | u32 index; |
| 200 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 201 | index = IOAM_MASK_DECAP_BIT (flow_ctx); |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 202 | //flow = pool_elt_at_index (hm->flows, index); |
| 203 | flow = &hm->flows[index]; |
| 204 | return (flow->ctx[option]); |
| 205 | } |
| 206 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 207 | static inline u8 |
| 208 | is_seqno_enabled (void) |
AkshayaNadahalli | ed4a2fd | 2016-08-09 13:38:04 +0530 | [diff] [blame] | 209 | { |
| 210 | return (ip6_hop_by_hop_ioam_main.has_seqno_option); |
| 211 | } |
| 212 | |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 213 | int ip6_trace_profile_setup (); |
AkshayaNadahalli | fdd81af | 2016-12-01 16:33:51 +0530 | [diff] [blame] | 214 | |
| 215 | static inline u32 |
| 216 | ioam_flow_add (u8 encap, u8 * flow_name) |
| 217 | { |
| 218 | ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; |
| 219 | flow_data_t *flow = 0; |
| 220 | u32 index = 0; |
| 221 | u8 i; |
| 222 | |
| 223 | pool_get (hm->flows, flow); |
Dave Barach | b7b9299 | 2018-10-17 10:38:51 -0400 | [diff] [blame] | 224 | clib_memset (flow, 0, sizeof (flow_data_t)); |
AkshayaNadahalli | fdd81af | 2016-12-01 16:33:51 +0530 | [diff] [blame] | 225 | |
| 226 | index = flow - hm->flows; |
| 227 | strncpy ((char *) flow->flow_name, (char *) flow_name, 31); |
| 228 | |
| 229 | if (!encap) |
| 230 | IOAM_SET_DECAP (index); |
| 231 | |
| 232 | for (i = 0; i < 255; i++) |
| 233 | { |
| 234 | if (hm->flow_handler[i]) |
| 235 | flow->ctx[i] = hm->flow_handler[i] (index, 1); |
| 236 | } |
| 237 | return (index); |
| 238 | } |
| 239 | |
AkshayaNadahalli | 1b56352 | 2017-01-23 22:05:35 +0530 | [diff] [blame] | 240 | always_inline ip6_hop_by_hop_option_t * |
| 241 | ip6_hbh_get_option (ip6_hop_by_hop_header_t * hbh0, u8 option_to_search) |
| 242 | { |
| 243 | ip6_hop_by_hop_option_t *opt0, *limit0; |
| 244 | u8 type0; |
| 245 | |
| 246 | if (!hbh0) |
| 247 | return NULL; |
| 248 | |
| 249 | opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1); |
| 250 | limit0 = (ip6_hop_by_hop_option_t *) |
| 251 | ((u8 *) hbh0 + ((hbh0->length + 1) << 3)); |
| 252 | |
| 253 | /* Scan the set of h-b-h options, process ones that we understand */ |
| 254 | while (opt0 < limit0) |
| 255 | { |
| 256 | type0 = opt0->type; |
| 257 | switch (type0) |
| 258 | { |
| 259 | case 0: /* Pad1 */ |
| 260 | opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1; |
| 261 | continue; |
| 262 | case 1: /* PadN */ |
| 263 | break; |
| 264 | default: |
| 265 | if (type0 == option_to_search) |
| 266 | return opt0; |
| 267 | break; |
| 268 | } |
| 269 | opt0 = |
| 270 | (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + |
| 271 | sizeof (ip6_hop_by_hop_option_t)); |
| 272 | } |
| 273 | return NULL; |
| 274 | } |
| 275 | |
Ole Troan | 944f548 | 2016-05-24 11:56:58 +0200 | [diff] [blame] | 276 | #endif /* __included_ip6_hop_by_hop_ioam_h__ */ |
Dave Barach | d7cb1b5 | 2016-12-09 09:52:16 -0500 | [diff] [blame] | 277 | |
| 278 | /* |
| 279 | * fd.io coding-style-patch-verification: ON |
| 280 | * |
| 281 | * Local Variables: |
| 282 | * eval: (c-set-style "gnu") |
| 283 | * End: |
| 284 | */ |