Skip to content

Commit 041add7

Browse files
Neale Rannsotroan
authored andcommitted
ipsec: Tunnel SA DSCP behaviour
Type: feature - use tunnel_encap_decap_flags to control the copying of DSCP/ECN/etc during IPSEC tunnel mode encap. - use DSCP value to have fixed encap value. Signed-off-by: Neale Ranns <nranns@cisco.com> Change-Id: If4f51fd4c1dcbb0422aac9bd078e5c14af5bf11f
1 parent 6287702 commit 041add7

20 files changed

+664
-72
lines changed

src/plugins/ikev2/ikev2.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,13 +1856,17 @@ ikev2_add_tunnel_from_main (ikev2_add_ipsec_tunnel_args_t * a)
18561856
IPSEC_PROTOCOL_ESP, a->encr_type,
18571857
&a->loc_ckey, a->integ_type, &a->loc_ikey,
18581858
a->flags, 0, a->salt_local, &zero_addr,
1859-
&zero_addr, NULL, a->src_port, a->dst_port);
1859+
&zero_addr, TUNNEL_ENCAP_DECAP_FLAG_NONE,
1860+
IP_DSCP_CS0, NULL, a->src_port, a->dst_port);
1861+
18601862
rv |= ipsec_sa_add_and_lock (a->remote_sa_id, a->remote_spi,
18611863
IPSEC_PROTOCOL_ESP, a->encr_type, &a->rem_ckey,
18621864
a->integ_type, &a->rem_ikey,
18631865
(a->flags | IPSEC_SA_FLAG_IS_INBOUND), 0,
18641866
a->salt_remote, &zero_addr,
1865-
&zero_addr, NULL, a->ipsec_over_udp_port,
1867+
&zero_addr, TUNNEL_ENCAP_DECAP_FLAG_NONE,
1868+
IP_DSCP_CS0, NULL,
1869+
a->ipsec_over_udp_port,
18661870
a->ipsec_over_udp_port);
18671871

18681872
rv |= ipsec_tun_protect_update (sw_if_index, NULL, a->local_sa_id, sas_in);

src/vnet/ip/ip.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,24 @@ format_ip_dscp (u8 * s, va_list * va)
155155
return (format (s, "unknown"));
156156
}
157157

158+
uword
159+
unformat_ip_dscp (unformat_input_t * input, va_list * args)
160+
{
161+
ip_dscp_t *dscp = va_arg (*args, ip_dscp_t *);
162+
163+
if (0)
164+
;
165+
#define _(n,v) \
166+
else if (unformat (input, #v)) \
167+
*dscp = IP_DSCP_##v;
168+
foreach_ip_dscp
169+
#undef _
170+
else
171+
return 0;
172+
173+
return 1;
174+
}
175+
158176
u8 *
159177
format_ip_ecn (u8 * s, va_list * va)
160178
{

src/vnet/ip/ip6_packet.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,31 +310,36 @@ typedef struct
310310
ip6_address_t src_address, dst_address;
311311
} ip6_header_t;
312312

313+
#define IP6_PACKET_TC_MASK 0x0FF00000
314+
#define IP6_PACKET_DSCP_MASK 0x0FC00000
315+
#define IP6_PACKET_ECN_MASK 0x00300000
316+
313317
always_inline ip_dscp_t
314318
ip6_traffic_class (const ip6_header_t * i)
315319
{
316-
return (i->ip_version_traffic_class_and_flow_label & 0x0FF00000) >> 20;
320+
return (i->ip_version_traffic_class_and_flow_label & IP6_PACKET_TC_MASK) >>
321+
20;
317322
}
318323

319324
static_always_inline ip_dscp_t
320325
ip6_traffic_class_network_order (const ip6_header_t * ip6)
321326
{
322327
return (clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label)
323-
& 0x0ff00000) >> 20;
328+
& IP6_PACKET_TC_MASK) >> 20;
324329
}
325330

326331
static_always_inline ip_dscp_t
327332
ip6_dscp_network_order (const ip6_header_t * ip6)
328333
{
329334
return (clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label)
330-
& 0x0fc00000) >> 22;
335+
& IP6_PACKET_DSCP_MASK) >> 22;
331336
}
332337

333338
static_always_inline ip_ecn_t
334339
ip6_ecn_network_order (const ip6_header_t * ip6)
335340
{
336341
return (clib_net_to_host_u32 (ip6->ip_version_traffic_class_and_flow_label)
337-
& 0x00300000) >> 20;
342+
& IP6_PACKET_ECN_MASK) >> 20;
338343
}
339344

340345
static_always_inline void

src/vnet/ip/ip_packet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
#include <vppinfra/byte_order.h>
4444
#include <vppinfra/error.h>
45+
#include <vppinfra/format.h>
4546

4647
typedef enum ip_protocol
4748
{
@@ -119,6 +120,7 @@ typedef enum ip_dscp_t_
119120
} __clib_packed ip_dscp_t;
120121

121122
extern u8 *format_ip_dscp (u8 * s, va_list * va);
123+
unformat_function_t unformat_ip_dscp;
122124

123125
/**
124126
* IP DSCP bit shift

src/vnet/ipsec/ah_encrypt.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <vnet/ipsec/ipsec.h>
2323
#include <vnet/ipsec/esp.h>
2424
#include <vnet/ipsec/ah.h>
25+
#include <vnet/tunnel/tunnel_dp.h>
2526

2627
#define foreach_ah_encrypt_next \
2728
_ (DROP, "error-drop") \
@@ -111,12 +112,13 @@ typedef struct
111112
{
112113
union
113114
{
115+
/* Variable fields in the IP header not covered by the AH
116+
* integrity check */
114117
struct
115118
{
116119
u8 hop_limit;
117120
u32 ip_version_traffic_class_and_flow_label;
118121
};
119-
120122
struct
121123
{
122124
u8 ttl;
@@ -209,8 +211,6 @@ ah_encrypt_inline (vlib_main_t * vm,
209211

210212
ssize_t adv;
211213
ih0 = vlib_buffer_get_current (b[0]);
212-
pd->ttl = ih0->ip4.ttl;
213-
pd->tos = ih0->ip4.tos;
214214

215215
if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
216216
{
@@ -246,10 +246,20 @@ ah_encrypt_inline (vlib_main_t * vm,
246246
ip_hdr_size = sizeof (ip6_header_t);
247247
oh6_0 = vlib_buffer_get_current (b[0]);
248248
pd->current_data = b[0]->current_data;
249-
250249
pd->hop_limit = ih6_0->ip6.hop_limit;
251-
pd->ip_version_traffic_class_and_flow_label =
250+
251+
oh6_0->ip6.ip_version_traffic_class_and_flow_label =
252252
ih6_0->ip6.ip_version_traffic_class_and_flow_label;
253+
254+
ip6_set_dscp_network_order (&oh6_0->ip6, sa0->dscp);
255+
256+
tunnel_encap_fixup_6o6 (sa0->tunnel_flags,
257+
&ih6_0->ip6, &oh6_0->ip6);
258+
259+
pd->ip_version_traffic_class_and_flow_label =
260+
oh6_0->ip6.ip_version_traffic_class_and_flow_label;
261+
oh6_0->ip6.ip_version_traffic_class_and_flow_label = 0;
262+
253263
if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
254264
{
255265
next_hdr_type = IP_PROTOCOL_IPV6;
@@ -275,8 +285,24 @@ ah_encrypt_inline (vlib_main_t * vm,
275285
{
276286
ip_hdr_size = sizeof (ip4_header_t);
277287
oh0 = vlib_buffer_get_current (b[0]);
278-
clib_memset (oh0, 0, sizeof (ip4_and_ah_header_t));
288+
pd->ttl = ih0->ip4.ttl;
289+
290+
if (sa0->dscp)
291+
pd->tos = sa0->dscp << 2;
292+
else
293+
{
294+
pd->tos = ih0->ip4.tos;
295+
if (!
296+
(sa0->tunnel_flags &
297+
TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP))
298+
pd->tos &= 0x3;
299+
if (!
300+
(sa0->tunnel_flags &
301+
TUNNEL_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
302+
pd->tos &= 0xfc;
303+
}
279304
pd->current_data = b[0]->current_data;
305+
clib_memset (oh0, 0, sizeof (ip4_and_ah_header_t));
280306

281307
if (PREDICT_TRUE (ipsec_sa_is_set_IS_TUNNEL (sa0)))
282308
{

src/vnet/ipsec/esp_encrypt.c

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <vnet/ipsec/ipsec.h>
2525
#include <vnet/ipsec/ipsec_tun.h>
2626
#include <vnet/ipsec/esp.h>
27+
#include <vnet/tunnel/tunnel_dp.h>
2728

2829
#define foreach_esp_encrypt_next \
2930
_(DROP4, "ip4-drop") \
@@ -743,9 +744,22 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
743744
u16 len = sizeof (ip6_header_t);
744745
hdr_len += len;
745746
ip6 = (ip6_header_t *) (payload - hdr_len);
746-
clib_memcpy_fast (ip6, &sa0->ip6_hdr, len);
747-
*next_hdr_ptr = (is_ip6 ?
748-
IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
747+
clib_memcpy_fast (ip6, &sa0->ip6_hdr, sizeof (ip6_header_t));
748+
749+
if (is_ip6)
750+
{
751+
*next_hdr_ptr = IP_PROTOCOL_IPV6;
752+
tunnel_encap_fixup_6o6 (sa0->tunnel_flags,
753+
(const ip6_header_t *) payload,
754+
ip6);
755+
}
756+
else
757+
{
758+
*next_hdr_ptr = IP_PROTOCOL_IP_IN_IP;
759+
tunnel_encap_fixup_4o6 (sa0->tunnel_flags,
760+
(const ip4_header_t *) payload,
761+
ip6);
762+
}
749763
len = payload_len_total + hdr_len - len;
750764
ip6->payload_length = clib_net_to_host_u16 (len);
751765
}
@@ -755,9 +769,22 @@ esp_encrypt_inline (vlib_main_t * vm, vlib_node_runtime_t * node,
755769
u16 len = sizeof (ip4_header_t);
756770
hdr_len += len;
757771
ip4 = (ip4_header_t *) (payload - hdr_len);
758-
clib_memcpy_fast (ip4, &sa0->ip4_hdr, len);
759-
*next_hdr_ptr = (is_ip6 ?
760-
IP_PROTOCOL_IPV6 : IP_PROTOCOL_IP_IN_IP);
772+
clib_memcpy_fast (ip4, &sa0->ip4_hdr, sizeof (ip4_header_t));
773+
774+
if (is_ip6)
775+
{
776+
*next_hdr_ptr = IP_PROTOCOL_IPV6;
777+
tunnel_encap_fixup_6o4_w_chksum (sa0->tunnel_flags,
778+
(const ip6_header_t *)
779+
payload, ip4);
780+
}
781+
else
782+
{
783+
*next_hdr_ptr = IP_PROTOCOL_IP_IN_IP;
784+
tunnel_encap_fixup_4o4_w_chksum (sa0->tunnel_flags,
785+
(const ip4_header_t *)
786+
payload, ip4);
787+
}
761788
len = payload_len_total + hdr_len;
762789
esp_update_ip4_hdr (ip4, len, /* is_transport */ 0, 0);
763790
}

src/vnet/ipsec/ipsec.api

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,25 @@ define ipsec_sad_entry_add_del
196196
bool is_add;
197197
vl_api_ipsec_sad_entry_t entry;
198198
};
199+
define ipsec_sad_entry_add_del_v2
200+
{
201+
u32 client_index;
202+
u32 context;
203+
bool is_add;
204+
vl_api_ipsec_sad_entry_v2_t entry;
205+
};
199206
define ipsec_sad_entry_add_del_reply
200207
{
201208
u32 context;
202209
i32 retval;
203210
u32 stat_index;
204211
};
212+
define ipsec_sad_entry_add_del_v2_reply
213+
{
214+
u32 context;
215+
i32 retval;
216+
u32 stat_index;
217+
};
205218

206219
/** \brief Add or Update Protection for a tunnel with IPSEC
207220
@@ -439,33 +452,24 @@ define ipsec_sa_dump
439452
u32 context;
440453
u32 sa_id;
441454
};
455+
define ipsec_sa_v2_dump
456+
{
457+
u32 client_index;
458+
u32 context;
459+
u32 sa_id;
460+
};
442461

443462
/** \brief IPsec security association database response
444463
@param context - sender context which was passed in the request
445-
@param sa_id - SA ID, policy-based SAs >=0, tunnel interface SAs = 0
464+
@param entry - The SA details
446465
@param sw_if_index - sw_if_index of tunnel interface, policy-based SAs = ~0
447-
@param spi - security parameter index
448-
@param protocol - IPsec protocol (value from ipsec_protocol_t)
449-
@param crypto_alg - crypto algorithm (value from ipsec_crypto_alg_t)
450-
@param crypto_key_len - length of crypto_key in bytes
451-
@param crypto_key - crypto keying material
452-
@param integ_alg - integrity algorithm (value from ipsec_integ_alg_t)
453-
@param integ_key_len - length of integ_key in bytes
454-
@param integ_key - integrity keying material
455-
@param use_esn - using extended sequence numbers when non-zero
456-
@param use_anti_replay - using anti-replay window when non-zero
457-
@param is_tunnel - IPsec tunnel mode when non-zero, else transport mode
458-
@param is_tunnel_ipv6 - If using tunnel mode, endpoints are IPv6
459-
@param tunnel_src_addr - Tunnel source address if using tunnel mode
460-
@param tunnel_dst_addr - Tunnel destination address is using tunnel mode
461466
@param salt - 4 byte salt
462467
@param seq - current sequence number for outbound
463468
@param seq_hi - high 32 bits of ESN for outbound
464469
@param last_seq - highest sequence number received inbound
465470
@param last_seq_hi - high 32 bits of highest ESN received inbound
466471
@param replay_window - bit map of seq nums received relative to last_seq if using anti-replay
467472
@param stat_index - index for the SA in the stats segment @ /net/ipsec/sa
468-
@param udp_encap - 1 if UDP encap enabled, 0 otherwise
469473
*/
470474
define ipsec_sa_details {
471475
u32 context;
@@ -479,6 +483,18 @@ define ipsec_sa_details {
479483

480484
u32 stat_index;
481485
};
486+
define ipsec_sa_v2_details {
487+
u32 context;
488+
vl_api_ipsec_sad_entry_v2_t entry;
489+
490+
vl_api_interface_index_t sw_if_index;
491+
u32 salt;
492+
u64 seq_outbound;
493+
u64 last_seq_inbound;
494+
u64 replay_window;
495+
496+
u32 stat_index;
497+
};
482498

483499
/** \brief Set new SA on IPsec interface
484500

0 commit comments

Comments
 (0)