17 #include "../ip/ip_frag.h" 19 #define IP4_MAP_T_DUAL_LOOP 1 63 }) ip4_mapt_pseudo_header_t;
66 #define frag_id_4to6(id) (id) 70 static u8 icmp_to_icmp6_updater_pointer_table[] =
88 IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip4->
protocol,
106 IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip4->
protocol,
126 case ICMP4_echo_reply:
127 *receiver_port = ((
u16 *) icmp)[2];
128 icmp->type = ICMP6_echo_reply;
130 case ICMP4_echo_request:
131 *receiver_port = ((
u16 *) icmp)[2];
132 icmp->type = ICMP6_echo_request;
134 case ICMP4_destination_unreachable:
140 case ICMP4_destination_unreachable_destination_unreachable_net:
141 case ICMP4_destination_unreachable_destination_unreachable_host:
142 icmp->type = ICMP6_destination_unreachable;
143 icmp->code = ICMP6_destination_unreachable_no_route_to_destination;
145 case ICMP4_destination_unreachable_protocol_unreachable:
146 icmp->type = ICMP6_parameter_problem;
147 icmp->code = ICMP6_parameter_problem_unrecognized_next_header;
149 case ICMP4_destination_unreachable_port_unreachable:
150 icmp->type = ICMP6_destination_unreachable;
151 icmp->code = ICMP6_destination_unreachable_port_unreachable;
153 case ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set:
155 ICMP6_packet_too_big;
158 u32 advertised_mtu = clib_net_to_host_u32 (*((
u32 *) (icmp + 1)));
160 advertised_mtu += 20;
162 advertised_mtu = 1000;
165 *((
u32 *) (icmp + 1)) = clib_host_to_net_u32 (advertised_mtu);
169 case ICMP4_destination_unreachable_source_route_failed:
170 case ICMP4_destination_unreachable_destination_network_unknown:
171 case ICMP4_destination_unreachable_destination_host_unknown:
172 case ICMP4_destination_unreachable_source_host_isolated:
173 case ICMP4_destination_unreachable_network_unreachable_for_type_of_service:
174 case ICMP4_destination_unreachable_host_unreachable_for_type_of_service:
176 ICMP6_destination_unreachable;
177 icmp->code = ICMP6_destination_unreachable_no_route_to_destination;
179 case ICMP4_destination_unreachable_network_administratively_prohibited:
180 case ICMP4_destination_unreachable_host_administratively_prohibited:
181 case ICMP4_destination_unreachable_communication_administratively_prohibited:
182 case ICMP4_destination_unreachable_precedence_cutoff_in_effect:
183 icmp->type = ICMP6_destination_unreachable;
185 ICMP6_destination_unreachable_destination_administratively_prohibited;
187 case ICMP4_destination_unreachable_host_precedence_violation:
193 case ICMP4_time_exceeded:
196 icmp->type = ICMP6_time_exceeded;
200 case ICMP4_parameter_problem:
206 case ICMP4_parameter_problem_pointer_indicates_error:
207 case ICMP4_parameter_problem_bad_length:
208 icmp->type = ICMP6_parameter_problem;
209 icmp->code = ICMP6_parameter_problem_erroneous_header_field;
212 icmp_to_icmp6_updater_pointer_table[*((
u8 *) (icmp + 1))];
216 *((
u32 *) (icmp + 1)) = clib_host_to_net_u32 (ptr);
239 icmp46_header_t *icmp;
242 u16 *inner_L4_checksum = 0;
243 ip6_frag_hdr_t *inner_frag;
245 u32 inner_frag_offset;
249 ip_len = clib_net_to_host_u16 (ip4->
length);
250 ASSERT (ip_len <= p->current_length);
252 icmp = (icmp46_header_t *) (ip4 + 1);
254 &recv_port, &inner_ip4))
256 *error = MAP_ERROR_ICMP;
269 *error = MAP_ERROR_ICMP;
288 *error = MAP_ERROR_FRAGMENTED;
293 -2 * (
sizeof (*ip6) -
sizeof (*ip4)) -
294 sizeof (*inner_frag));
300 icmp = (icmp46_header_t *) (ip4 + 1);
304 sizeof (*ip4) -
sizeof (*ip6) -
305 sizeof (*inner_frag));
307 (ip6_frag_hdr_t *)
u8_ptr_add (inner_ip6,
sizeof (*inner_ip6));
310 sizeof (*ip6) - 2 *
sizeof (*ip4) +
311 sizeof (*inner_frag));
326 icmp = (icmp46_header_t *)
u8_ptr_add (ip4,
sizeof (*ip4));
329 sizeof (*ip4) -
sizeof (*ip6));
337 inner_L4_checksum = &((
tcp_header_t *) (inner_ip4 + 1))->checksum;
345 inner_L4_checksum = &((
udp_header_t *) (inner_ip4 + 1))->checksum;
346 if (!*inner_L4_checksum)
350 *error = MAP_ERROR_ICMP;
358 else if (inner_ip4->
protocol == IP_PROTOCOL_ICMP)
362 icmp46_header_t *inner_icmp = (icmp46_header_t *) (inner_ip4 + 1);
363 csum = inner_icmp->checksum;
366 inner_icmp->type = (inner_icmp->type == ICMP4_echo_request) ?
367 ICMP6_echo_request : ICMP6_echo_reply;
374 inner_L4_checksum = &inner_icmp->checksum;
375 inner_ip4->
protocol = IP_PROTOCOL_ICMP6;
385 csum = *inner_L4_checksum;
389 clib_host_to_net_u32 ((6 << 28) + (inner_ip4->
tos << 20));
406 inner_frag->next_hdr = inner_ip6->
protocol;
407 inner_frag->identification = inner_frag_id;
409 inner_frag->fragment_offset_and_more =
411 inner_ip6->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
413 clib_host_to_net_u16 (clib_net_to_host_u16
415 sizeof (*inner_frag));
430 clib_host_to_net_u16 (clib_net_to_host_u16 (ip4->
length) -
436 clib_host_to_net_u32 ((6 << 28) + (ip4->
tos << 20));
450 ip6->
payload_length = clib_host_to_net_u16 (1280 -
sizeof (*ip6));
473 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
482 while (n_left_from > 0)
486 while (n_left_from > 0 && n_left_to_next > 0)
490 ip4_mapt_icmp_next_t next0;
496 pi0 = to_next[0] = from[0];
501 error0 = MAP_ERROR_NONE;
511 _ip4_map_t_icmp (d0, p0, &error0);
525 map_domain_index, 1, len0);
533 to_next, n_left_to_next, pi0,
545 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
550 while (n_left_from > 0)
554 while (n_left_from > 0 && n_left_to_next > 0)
560 ip6_frag_hdr_t *frag0;
561 ip4_mapt_pseudo_header_t *pheader0;
562 ip4_mapt_fragmented_next_t next0;
565 pi0 = to_next[0] = from[0];
581 sizeof (*ip40) -
sizeof (*frag0));
584 sizeof (*ip40) -
sizeof (*frag0) -
587 sizeof (*ip40) -
sizeof (*ip60) -
594 IP_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP6 : ip40->
protocol;
597 frag0->fragment_offset_and_more =
604 clib_host_to_net_u32 ((6 << 28) + (ip40->
tos << 20));
606 clib_host_to_net_u16 (clib_net_to_host_u16 (ip40->
length) -
607 sizeof (*ip40) +
sizeof (*frag0));
609 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
624 to_next, n_left_to_next, pi0,
636 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
641 while (n_left_from > 0)
645 #ifdef IP4_MAP_T_DUAL_LOOP 646 while (n_left_from >= 4 && n_left_to_next >= 2)
653 u16 *checksum0, *checksum1;
654 ip6_frag_hdr_t *frag0, *frag1;
655 u32 frag_id0, frag_id1;
656 ip4_mapt_pseudo_header_t *pheader0, *pheader1;
657 ip4_mapt_tcp_udp_next_t next0, next1;
659 pi0 = to_next[0] = from[0];
660 pi1 = to_next[1] = from[1];
690 (!*checksum0 && ip40->
protocol == IP_PROTOCOL_UDP))
693 clib_host_to_net_u16 (ip40->
length) -
sizeof (*ip40);
702 clib_host_to_net_u16 (IP_PROTOCOL_UDP));
708 (!*checksum1 && ip41->
protocol == IP_PROTOCOL_UDP))
711 clib_host_to_net_u16 (ip41->
length) -
sizeof (*ip40);
720 clib_host_to_net_u16 (IP_PROTOCOL_UDP));
738 sizeof (*ip40) -
sizeof (*ip60) -
746 sizeof (*ip40) -
sizeof (*ip60) -
764 sizeof (*ip40) -
sizeof (*ip60) -
772 sizeof (*ip40) -
sizeof (*ip60) -
785 clib_host_to_net_u32 ((6 << 28) + (ip40->
tos << 20));
787 clib_host_to_net_u32 ((6 << 28) + (ip41->
tos << 20));
798 frag0->identification = frag_id0;
800 frag0->fragment_offset_and_more =
802 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
810 frag1->identification = frag_id1;
812 frag1->fragment_offset_and_more =
814 ip61->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
857 to_next, n_left_to_next, pi0, pi1,
862 while (n_left_from > 0 && n_left_to_next > 0)
870 ip6_frag_hdr_t *frag0;
872 ip4_mapt_pseudo_header_t *pheader0;
873 ip4_mapt_tcp_udp_next_t next0;
875 pi0 = to_next[0] = from[0];
897 (!*checksum0 && ip40->
protocol == IP_PROTOCOL_UDP))
900 clib_host_to_net_u16 (ip40->
length) -
sizeof (*ip40);
909 clib_host_to_net_u16 (IP_PROTOCOL_UDP));
925 sizeof (*ip40) -
sizeof (*ip60) -
933 sizeof (*ip40) -
sizeof (*ip60) -
946 clib_host_to_net_u32 ((6 << 28) + (ip40->
tos << 20));
954 frag0->identification = frag_id0;
956 frag0->fragment_offset_and_more =
958 ip60->
protocol = IP_PROTOCOL_IPV6_FRAGMENTATION;
985 to_next, n_left_to_next, pi0,
997 u8 * error0, ip4_mapt_next_t * next0)
1009 *error0 = (*dst_port0 == -1) ? MAP_ERROR_FRAGMENT_MEMORY : *error0;
1016 *error0 = ip4_len0 < 40 ? MAP_ERROR_MALFORMED : *error0;
1023 *error0 = ip4_len0 < 28 ? MAP_ERROR_MALFORMED : *error0;
1026 else if (ip40->
protocol == IP_PROTOCOL_ICMP)
1031 else if (((icmp46_header_t *)
u8_ptr_add (ip40,
sizeof (*ip40)))->code
1033 || ((icmp46_header_t *)
1035 sizeof (*ip40)))->code == ICMP4_echo_request)
1040 *error0 = MAP_ERROR_BAD_PROTOCOL;
1047 u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
1056 while (n_left_from > 0)
1060 #ifdef IP4_MAP_T_DUAL_LOOP 1061 while (n_left_from >= 4 && n_left_to_next >= 2)
1067 ip4_mapt_next_t next0 = 0, next1 = 0;
1068 u16 ip4_len0, ip4_len1;
1070 i32 dst_port0, dst_port1;
1071 ip4_mapt_pseudo_header_t *pheader0, *pheader1;
1073 pi0 = to_next[0] = from[0];
1074 pi1 = to_next[1] = from[1];
1078 n_left_to_next -= 2;
1079 error0 = MAP_ERROR_NONE;
1080 error1 = MAP_ERROR_NONE;
1086 ip4_len0 = clib_host_to_net_u16 (ip40->
length);
1087 ip4_len1 = clib_host_to_net_u16 (ip41->
length);
1092 error0 = MAP_ERROR_UNKNOWN;
1099 error1 = MAP_ERROR_UNKNOWN;
1130 pheader0->daddr.as_u64[0] =
1132 pheader0->daddr.as_u64[1] =
1134 pheader1->daddr.as_u64[0] =
1136 pheader1->daddr.as_u64[1] =
1144 error0 = MAP_ERROR_FRAGMENT_MEMORY;
1152 error1 = MAP_ERROR_FRAGMENT_MEMORY;
1161 map_domain_index, 1,
1162 clib_net_to_host_u16 (ip40->
1172 map_domain_index, 1,
1173 clib_net_to_host_u16 (ip41->
1182 n_left_to_next, pi0, pi1, next0,
1187 while (n_left_from > 0 && n_left_to_next > 0)
1193 ip4_mapt_next_t next0;
1197 ip4_mapt_pseudo_header_t *pheader0;
1199 pi0 = to_next[0] = from[0];
1203 n_left_to_next -= 1;
1204 error0 = MAP_ERROR_NONE;
1208 ip4_len0 = clib_host_to_net_u16 (ip40->
length);
1212 error0 = MAP_ERROR_UNKNOWN;
1232 pheader0->daddr.as_u64[0] =
1234 pheader0->daddr.as_u64[1] =
1245 error0 = MAP_ERROR_UNKNOWN;
1254 map_domain_index, 1,
1255 clib_net_to_host_u16 (ip40->
1262 to_next, n_left_to_next, pi0,
1270 static char *map_t_error_strings[] = {
1271 #define _(sym,string) string, 1279 .name =
"ip4-map-t-fragmented",
1280 .vector_size =
sizeof(
u32),
1285 .error_strings = map_t_error_strings,
1299 .name =
"ip4-map-t-icmp",
1300 .vector_size =
sizeof(
u32),
1305 .error_strings = map_t_error_strings,
1319 .name =
"ip4-map-t-tcp-udp",
1320 .vector_size =
sizeof(
u32),
1325 .error_strings = map_t_error_strings,
1339 .name =
"ip4-map-t",
1340 .vector_size =
sizeof(
u32),
1345 .error_strings = map_t_error_strings,
#define map_ip4_reass_lock()
#define IP6_FRAG_NODE_NAME
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
static_always_inline void ip4_map_t_classify(vlib_buffer_t *p0, map_domain_t *d0, ip4_header_t *ip40, u16 ip4_len0, i32 *dst_port0, u8 *error0, ip4_mapt_next_t *next0)
static ip_csum_t ip_csum_with_carry(ip_csum_t sum, ip_csum_t x)
static_always_inline i32 ip4_map_fragment_get_port(ip4_header_t *ip4)
vlib_error_t * errors
Vector of errors for this node.
struct _tcp_header tcp_header_t
#define u16_net_add(u, val)
static uword ip4_map_t_icmp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword ip4_map_t(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static_always_inline void ip4_map_t_embedded_address(map_domain_t *d, ip6_address_t *ip6, const ip4_address_t *ip4)
#define static_always_inline
ip_csum_t ip_incremental_checksum(ip_csum_t sum, void *_data, uword n_bytes)
vlib_combined_counter_main_t * domain_counters
ip4_mapt_fragmented_next_t
static int ip4_get_fragment_offset(ip4_header_t *i)
static_always_inline int ip4_icmp_to_icmp6_in_place(icmp46_header_t *icmp, u32 icmp_len, i32 *receiver_port, ip4_header_t **inner_ip4)
static int ip4_is_fragment(ip4_header_t *i)
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
u16 current_length
Nbytes between current data and the end of this buffer.
static_always_inline u64 map_get_pfx_net(map_domain_t *d, u32 addr, u16 port)
uword os_get_cpu_number(void)
static_always_inline u64 map_get_sfx_net(map_domain_t *d, u32 addr, u16 port)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
map_ip4_reass_t * map_ip4_reass_get(u32 src, u32 dst, u16 fragment_id, u8 protocol, u32 **pi_to_drop)
i32 ip4_get_port(ip4_header_t *ip, map_dir_e dir, u16 buffer_len)
#define vlib_validate_buffer_enqueue_x2(vm, node, next_index, to_next, n_left_to_next, bi0, bi1, next0, next1)
Finish enqueueing two buffers forward in the graph.
#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.
#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).
vlib_error_t error
Error code for buffers to be enqueued to error handler.
#define IP4_HEADER_FLAG_MORE_FRAGMENTS
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
#define clib_memcpy(a, b, c)
static int ip4_is_first_fragment(ip4_header_t *i)
#define foreach_map_error
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
#define u8_ptr_add(ptr, index)
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 cpu_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
#define map_ip4_reass_unlock()
u8 * format_map_trace(u8 *s, va_list *args)
static uword ip4_map_t_tcp_udp(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static uword ip4_map_t_fragmented(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
A collection of combined counters.
static_always_inline map_domain_t * ip4_map_get_domain(u32 mdi, u32 *map_domain_index)
static_always_inline int ip4_map_fragment_cache(ip4_header_t *ip4, u16 port)
#define VLIB_REGISTER_NODE(x,...)
typedef CLIB_PACKED(struct{ip6_address_t daddr;ip6_address_t saddr;u8 unused[28];})
#define ip6_frag_hdr_offset_and_more(offset, more)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static u16 ip_csum_fold(ip_csum_t c)
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)