@@ -124,8 +124,8 @@ static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb,
124124 return flowlabel ;
125125}
126126
127- /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
128- int seg6_do_srh_encap ( struct sk_buff * skb , struct ipv6_sr_hdr * osrh , int proto )
127+ static int __seg6_do_srh_encap ( struct sk_buff * skb , struct ipv6_sr_hdr * osrh ,
128+ int proto , struct dst_entry * cache_dst )
129129{
130130 struct dst_entry * dst = skb_dst (skb );
131131 struct net * net = dev_net (dst -> dev );
@@ -137,7 +137,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
137137 hdrlen = (osrh -> hdrlen + 1 ) << 3 ;
138138 tot_len = hdrlen + sizeof (* hdr );
139139
140- err = skb_cow_head (skb , tot_len + skb -> mac_len );
140+ err = skb_cow_head (skb , tot_len + dst_dev_overhead ( cache_dst , skb ) );
141141 if (unlikely (err ))
142142 return err ;
143143
@@ -197,11 +197,18 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
197197
198198 return 0 ;
199199}
200+
201+ /* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
202+ int seg6_do_srh_encap (struct sk_buff * skb , struct ipv6_sr_hdr * osrh , int proto )
203+ {
204+ return __seg6_do_srh_encap (skb , osrh , proto , NULL );
205+ }
200206EXPORT_SYMBOL_GPL (seg6_do_srh_encap );
201207
202208/* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */
203209static int seg6_do_srh_encap_red (struct sk_buff * skb ,
204- struct ipv6_sr_hdr * osrh , int proto )
210+ struct ipv6_sr_hdr * osrh , int proto ,
211+ struct dst_entry * cache_dst )
205212{
206213 __u8 first_seg = osrh -> first_segment ;
207214 struct dst_entry * dst = skb_dst (skb );
@@ -230,7 +237,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
230237
231238 tot_len = red_hdrlen + sizeof (struct ipv6hdr );
232239
233- err = skb_cow_head (skb , tot_len + skb -> mac_len );
240+ err = skb_cow_head (skb , tot_len + dst_dev_overhead ( cache_dst , skb ) );
234241 if (unlikely (err ))
235242 return err ;
236243
@@ -317,16 +324,16 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
317324 return 0 ;
318325}
319326
320- /* insert an SRH within an IPv6 packet, just after the IPv6 header */
321- int seg6_do_srh_inline ( struct sk_buff * skb , struct ipv6_sr_hdr * osrh )
327+ static int __seg6_do_srh_inline ( struct sk_buff * skb , struct ipv6_sr_hdr * osrh ,
328+ struct dst_entry * cache_dst )
322329{
323330 struct ipv6hdr * hdr , * oldhdr ;
324331 struct ipv6_sr_hdr * isrh ;
325332 int hdrlen , err ;
326333
327334 hdrlen = (osrh -> hdrlen + 1 ) << 3 ;
328335
329- err = skb_cow_head (skb , hdrlen + skb -> mac_len );
336+ err = skb_cow_head (skb , hdrlen + dst_dev_overhead ( cache_dst , skb ) );
330337 if (unlikely (err ))
331338 return err ;
332339
@@ -369,9 +376,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
369376
370377 return 0 ;
371378}
372- EXPORT_SYMBOL_GPL (seg6_do_srh_inline );
373379
374- static int seg6_do_srh (struct sk_buff * skb )
380+ static int seg6_do_srh (struct sk_buff * skb , struct dst_entry * cache_dst )
375381{
376382 struct dst_entry * dst = skb_dst (skb );
377383 struct seg6_iptunnel_encap * tinfo ;
@@ -384,7 +390,7 @@ static int seg6_do_srh(struct sk_buff *skb)
384390 if (skb -> protocol != htons (ETH_P_IPV6 ))
385391 return - EINVAL ;
386392
387- err = seg6_do_srh_inline (skb , tinfo -> srh );
393+ err = __seg6_do_srh_inline (skb , tinfo -> srh , cache_dst );
388394 if (err )
389395 return err ;
390396 break ;
@@ -402,9 +408,11 @@ static int seg6_do_srh(struct sk_buff *skb)
402408 return - EINVAL ;
403409
404410 if (tinfo -> mode == SEG6_IPTUN_MODE_ENCAP )
405- err = seg6_do_srh_encap (skb , tinfo -> srh , proto );
411+ err = __seg6_do_srh_encap (skb , tinfo -> srh ,
412+ proto , cache_dst );
406413 else
407- err = seg6_do_srh_encap_red (skb , tinfo -> srh , proto );
414+ err = seg6_do_srh_encap_red (skb , tinfo -> srh ,
415+ proto , cache_dst );
408416
409417 if (err )
410418 return err ;
@@ -425,11 +433,13 @@ static int seg6_do_srh(struct sk_buff *skb)
425433 skb_push (skb , skb -> mac_len );
426434
427435 if (tinfo -> mode == SEG6_IPTUN_MODE_L2ENCAP )
428- err = seg6_do_srh_encap (skb , tinfo -> srh ,
429- IPPROTO_ETHERNET );
436+ err = __seg6_do_srh_encap (skb , tinfo -> srh ,
437+ IPPROTO_ETHERNET ,
438+ cache_dst );
430439 else
431440 err = seg6_do_srh_encap_red (skb , tinfo -> srh ,
432- IPPROTO_ETHERNET );
441+ IPPROTO_ETHERNET ,
442+ cache_dst );
433443
434444 if (err )
435445 return err ;
@@ -444,6 +454,13 @@ static int seg6_do_srh(struct sk_buff *skb)
444454 return 0 ;
445455}
446456
457+ /* insert an SRH within an IPv6 packet, just after the IPv6 header */
458+ int seg6_do_srh_inline (struct sk_buff * skb , struct ipv6_sr_hdr * osrh )
459+ {
460+ return __seg6_do_srh_inline (skb , osrh , NULL );
461+ }
462+ EXPORT_SYMBOL_GPL (seg6_do_srh_inline );
463+
447464static int seg6_input_finish (struct net * net , struct sock * sk ,
448465 struct sk_buff * skb )
449466{
@@ -458,31 +475,33 @@ static int seg6_input_core(struct net *net, struct sock *sk,
458475 struct seg6_lwt * slwt ;
459476 int err ;
460477
461- err = seg6_do_srh (skb );
462- if (unlikely (err ))
463- goto drop ;
464-
465478 slwt = seg6_lwt_lwtunnel (orig_dst -> lwtstate );
466479
467480 local_bh_disable ();
468481 dst = dst_cache_get (& slwt -> cache );
482+ local_bh_enable ();
483+
484+ err = seg6_do_srh (skb , dst );
485+ if (unlikely (err ))
486+ goto drop ;
469487
470488 if (!dst ) {
471489 ip6_route_input (skb );
472490 dst = skb_dst (skb );
473491 if (!dst -> error ) {
492+ local_bh_disable ();
474493 dst_cache_set_ip6 (& slwt -> cache , dst ,
475494 & ipv6_hdr (skb )-> saddr );
495+ local_bh_enable ();
476496 }
497+
498+ err = skb_cow_head (skb , LL_RESERVED_SPACE (dst -> dev ));
499+ if (unlikely (err ))
500+ goto drop ;
477501 } else {
478502 skb_dst_drop (skb );
479503 skb_dst_set (skb , dst );
480504 }
481- local_bh_enable ();
482-
483- err = skb_cow_head (skb , LL_RESERVED_SPACE (dst -> dev ));
484- if (unlikely (err ))
485- goto drop ;
486505
487506 if (static_branch_unlikely (& nf_hooks_lwtunnel_enabled ))
488507 return NF_HOOK (NFPROTO_IPV6 , NF_INET_LOCAL_OUT ,
@@ -528,16 +547,16 @@ static int seg6_output_core(struct net *net, struct sock *sk,
528547 struct seg6_lwt * slwt ;
529548 int err ;
530549
531- err = seg6_do_srh (skb );
532- if (unlikely (err ))
533- goto drop ;
534-
535550 slwt = seg6_lwt_lwtunnel (orig_dst -> lwtstate );
536551
537552 local_bh_disable ();
538553 dst = dst_cache_get (& slwt -> cache );
539554 local_bh_enable ();
540555
556+ err = seg6_do_srh (skb , dst );
557+ if (unlikely (err ))
558+ goto drop ;
559+
541560 if (unlikely (!dst )) {
542561 struct ipv6hdr * hdr = ipv6_hdr (skb );
543562 struct flowi6 fl6 ;
@@ -559,15 +578,15 @@ static int seg6_output_core(struct net *net, struct sock *sk,
559578 local_bh_disable ();
560579 dst_cache_set_ip6 (& slwt -> cache , dst , & fl6 .saddr );
561580 local_bh_enable ();
581+
582+ err = skb_cow_head (skb , LL_RESERVED_SPACE (dst -> dev ));
583+ if (unlikely (err ))
584+ goto drop ;
562585 }
563586
564587 skb_dst_drop (skb );
565588 skb_dst_set (skb , dst );
566589
567- err = skb_cow_head (skb , LL_RESERVED_SPACE (dst -> dev ));
568- if (unlikely (err ))
569- goto drop ;
570-
571590 if (static_branch_unlikely (& nf_hooks_lwtunnel_enabled ))
572591 return NF_HOOK (NFPROTO_IPV6 , NF_INET_LOCAL_OUT , net , sk , skb ,
573592 NULL , skb_dst (skb )-> dev , dst_output );
0 commit comments