allow marking IPv6 with a do not fragment flag for ip6_output

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

allow marking IPv6 with a do not fragment flag for ip6_output

David Gwynne-5
ipv6 packets dont have a DF bit you can set in the header, you have
to pass it as an option to ip6_output if you want that behaviour
on output. however, ip6_send makes it hard to pass ip6 options to
ip6_output because you give it an mbuf, and hope for the best in
the future.

to cope with this, im proposing we treat "dont fragment on output"
for ipv6 as a checksum flag on an mbuf. the diff below implements
this:

Index: sys/mbuf.h
===================================================================
RCS file: /cvs/src/sys/sys/mbuf.h,v
retrieving revision 1.234
diff -u -p -r1.234 mbuf.h
--- sys/mbuf.h 9 Feb 2018 02:26:33 -0000 1.234
+++ sys/mbuf.h 10 Feb 2018 09:38:40 -0000
@@ -224,12 +224,14 @@ struct mbuf {
 #define M_ICMP_CSUM_OUT 0x0200 /* ICMP/ICMPv6 checksum needed */
 #define M_ICMP_CSUM_IN_OK 0x0400 /* ICMP/ICMPv6 checksum verified */
 #define M_ICMP_CSUM_IN_BAD 0x0800 /* ICMP/ICMPv6 checksum bad */
+#define M_IPV6_DF_OUT 0x1000 /* don't fragment outgoing IPv6 */
 
 #ifdef _KERNEL
 #define MCS_BITS \
     ("\20\1IPV4_CSUM_OUT\2TCP_CSUM_OUT\3UDP_CSUM_OUT\4IPV4_CSUM_IN_OK" \
     "\5IPV4_CSUM_IN_BAD\6TCP_CSUM_IN_OK\7TCP_CSUM_IN_BAD\10UDP_CSUM_IN_OK" \
-    "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD")
+    "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD" \
+    "\15IPV6_NODF_OUT")
 #endif
 
 /* mbuf types */
Index: netinet6/ip6_output.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
retrieving revision 1.232
diff -u -p -r1.232 ip6_output.c
--- netinet6/ip6_output.c 1 Sep 2017 15:05:31 -0000 1.232
+++ netinet6/ip6_output.c 10 Feb 2018 09:38:40 -0000
@@ -656,7 +656,10 @@ reroute:
  */
  tlen = m->m_pkthdr.len;
 
- if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG))
+ if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) {
+ CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
+ dontfrag = 1;
+ } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG))
  dontfrag = 1;
  else
  dontfrag = 0;

Reply | Threaded
Open this post in threaded view
|

Re: allow marking IPv6 with a do not fragment flag for ip6_output

Claudio Jeker
On Sat, Feb 10, 2018 at 09:03:10PM +1000, David Gwynne wrote:

> ipv6 packets dont have a DF bit you can set in the header, you have
> to pass it as an option to ip6_output if you want that behaviour
> on output. however, ip6_send makes it hard to pass ip6 options to
> ip6_output because you give it an mbuf, and hope for the best in
> the future.
>
> to cope with this, im proposing we treat "dont fragment on output"
> for ipv6 as a checksum flag on an mbuf. the diff below implements
> this:
>

Not a fan of this since this is yet another special hack but I see why you
need it and how hard it is to fix it properly.

Grumbling ok claudio@

> Index: sys/mbuf.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/mbuf.h,v
> retrieving revision 1.234
> diff -u -p -r1.234 mbuf.h
> --- sys/mbuf.h 9 Feb 2018 02:26:33 -0000 1.234
> +++ sys/mbuf.h 10 Feb 2018 09:38:40 -0000
> @@ -224,12 +224,14 @@ struct mbuf {
>  #define M_ICMP_CSUM_OUT 0x0200 /* ICMP/ICMPv6 checksum needed */
>  #define M_ICMP_CSUM_IN_OK 0x0400 /* ICMP/ICMPv6 checksum verified */
>  #define M_ICMP_CSUM_IN_BAD 0x0800 /* ICMP/ICMPv6 checksum bad */
> +#define M_IPV6_DF_OUT 0x1000 /* don't fragment outgoing IPv6 */
>  
>  #ifdef _KERNEL
>  #define MCS_BITS \
>      ("\20\1IPV4_CSUM_OUT\2TCP_CSUM_OUT\3UDP_CSUM_OUT\4IPV4_CSUM_IN_OK" \
>      "\5IPV4_CSUM_IN_BAD\6TCP_CSUM_IN_OK\7TCP_CSUM_IN_BAD\10UDP_CSUM_IN_OK" \
> -    "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD")
> +    "\11UDP_CSUM_IN_BAD\12ICMP_CSUM_OUT\13ICMP_CSUM_IN_OK\14ICMP_CSUM_IN_BAD" \
> +    "\15IPV6_NODF_OUT")
>  #endif
>  
>  /* mbuf types */
> Index: netinet6/ip6_output.c
> ===================================================================
> RCS file: /cvs/src/sys/netinet6/ip6_output.c,v
> retrieving revision 1.232
> diff -u -p -r1.232 ip6_output.c
> --- netinet6/ip6_output.c 1 Sep 2017 15:05:31 -0000 1.232
> +++ netinet6/ip6_output.c 10 Feb 2018 09:38:40 -0000
> @@ -656,7 +656,10 @@ reroute:
>   */
>   tlen = m->m_pkthdr.len;
>  
> - if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG))
> + if (ISSET(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT)) {
> + CLR(m->m_pkthdr.csum_flags, M_IPV6_DF_OUT);
> + dontfrag = 1;
> + } else if (opt && ISSET(opt->ip6po_flags, IP6PO_DONTFRAG))
>   dontfrag = 1;
>   else
>   dontfrag = 0;
>

--
:wq Claudio