IPv6 multicast packet size

Hideki Yamamoto hyama99 at gmail.com
Sun Feb 21 22:02:21 UTC 2010


Hi,

I have encountered IPv6 multicast problem.
I cannot send UDP packet longer than Shortest MTU.
It seems the bug of IPv6 multicast kernel.
I used the same application from FreeBSD 4.11. On that old version,
any problems happens.  When I would like to change the platform of
this application from 4.11 to 7.2 or later, I encountered this
problem.
Does anyone have any information about this problem?

The followings are OS information I have tested, the result of
Tshark command, and source code of test program.

Best regards,

Hideki Yamamoto

--------------------------------------------------------------------------
OS information
--------------------------------------------------------------------------
# sysctl -a |grep v6
net.inet.tcp.v6mssdflt: 1024
net.inet6.ip6.v6only: 1
# sysctl -a |grep mtu
net.inet.tcp.path_mtu_discovery: 1
net.inet.sctp.pmtu_raise_time: 600
net.inet6.ip6.mcast_pmtu: 0
# uname -a
FreeBSD tulip 9.0-CURRENT FreeBSD 9.0-CURRENT #16: Fri Jan 15 05:25:24
JST 2010     root at tulip:/usr/obj/usr/src/sys/tulip8  i386
tulip#

--------------------------------------------------------------------------
Tshark output that shows the packets are devided into two packtet when
delivering 1400 byte lenghth packets.
--------------------------------------------------------------------------
# ./udp -s 1400 -o &
# tshark -VV -i fxp1 host ff3e::9800:600 |grep -v aaaaaaaaa
Capturing on fxp1
Frame 1 (1294 bytes on wire, 1294 bytes captured)
   Arrival Time: Feb 21, 2010 17:35:08.560297000
   [Time delta from previous captured frame: 0.000000000 seconds]
   [Time delta from previous displayed frame: 0.000000000 seconds]
   [Time since reference or first frame: 0.000000000 seconds]
   Frame Number: 1
   Frame Length: 1294 bytes
   Capture Length: 1294 bytes
   [Frame is marked: False]
   [Protocols in frame: eth:ipv6:data]
Ethernet II, Src: Intel_89:d6:d9 (00:d0:b7:89:d6:d9), Dst:
IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
   Destination: IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
       Address: IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
       .... ...1 .... .... .... .... = IG bit: Group address
(multicast/broadcast)
       .... ..1. .... .... .... .... = LG bit: Locally administered
address (this is NOT the factory default)
   Source: Intel_89:d6:d9 (00:d0:b7:89:d6:d9)
       Address: Intel_89:d6:d9 (00:d0:b7:89:d6:d9)
       .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
       .... ..0. .... .... .... .... = LG bit: Globally unique address
(factory default)
   Type: IPv6 (0x86dd)
Internet Protocol Version 6
   0110 .... = Version: 6
       [0110 .... = This field makes the filter "ip.version == 6" possible: 6]
   .... 0000 0000 .... .... .... .... .... = Traffic class: 0x00000000
   .... .... .... 0000 0000 0000 0000 0000 = Flowlabel: 0x00000000
   Payload length: 1240
   Next header: IPv6 fragment (0x2c)
   Hop limit: 1
   Source: 2001:2a0:806:206:2d0:b7ff:fe89:d6d9
(2001:2a0:806:206:2d0:b7ff:fe89:d6d9)
   Destination: ff3e::9800:600 (ff3e::9800:600)
   Fragmentation Header
       Next header: UDP (0x11)
       0000 0000 0000 0... = Offset: 0 (0x0000)
       .... .... .... ...1 = More Fragment: Yes
       Identification: 0xc31d92fa
Data (1232 bytes)

0000  5d 61 46 50 05 80 b0 d6 61 61 61 61 61 61 61 61   ]aFP....aaaaaaaa
   Data: 5D6146500580B0D661616161616161616161616161616161...
   [Length: 1232]

Frame 2 (238 bytes on wire, 238 bytes captured)
   Arrival Time: Feb 21, 2010 17:35:08.560324000
   [Time delta from previous captured frame: 0.000027000 seconds]
   [Time delta from previous displayed frame: 0.000027000 seconds]
   [Time since reference or first frame: 0.000027000 seconds]
   Frame Number: 2
   Frame Length: 238 bytes
   Capture Length: 238 bytes
   [Frame is marked: False]
   [Protocols in frame: eth:ipv6:udp:data]
Ethernet II, Src: Intel_89:d6:d9 (00:d0:b7:89:d6:d9), Dst:
IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
   Destination: IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
       Address: IPv6mcast_98:00:06:00 (33:33:98:00:06:00)
       .... ...1 .... .... .... .... = IG bit: Group address
(multicast/broadcast)
       .... ..1. .... .... .... .... = LG bit: Locally administered
address (this is NOT the factory default)
   Source: Intel_89:d6:d9 (00:d0:b7:89:d6:d9)
       Address: Intel_89:d6:d9 (00:d0:b7:89:d6:d9)
       .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
       .... ..0. .... .... .... .... = LG bit: Globally unique address
(factory default)
   Type: IPv6 (0x86dd)

------
/**********************************************************************
udp.c (modified for MC Send Support)
***********************************************************************/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <err.h>
#include <errno.h>
#include <ifaddrs.h>

 // Modify send_addr to Multicast Address
char *send_addr="ff3e::9800:600";
char *send_port="18000";

char *recv_addr="2001:99::1";
char *recv_port="16000";
int send_s;
int only_out=0;
int only_in=0;
int out_packet_size;
struct addrinfo *send_res;

// Add for MC support
char *out_if="fxp1";

main(ac,av)
int ac;
char **av;
{
   int c;

   while ((c = getopt(ac, av, "s:oi")) != -1) {
       switch (c) {
       case 'o':
           only_out++;
           break;
       case 'i':
           only_in++;
           break;
       case 's':
           out_packet_size = atoi(optarg);
           break;
       default:
           Usage();
           exit (1);
       }
   }
   if( only_in && only_out ){
       Usage();
       exit (1);
   }

   if( only_in == 0 ){
       create_send_socket();
       send_v6_udp();
       exit;
   }
   recv_v6_udp();
}
Usage()
{
   printf("Usage: udpgw [-o][-i][-s output_packet_size]\n");

}
create_send_socket()
{
   struct addrinfo hints;
   int error;
   struct sockaddr_in6 *sin6;// Add for MC Support
   int ifindex;// Add for MC Support


   memset(&hints, 0, sizeof(hints));
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_DGRAM;
   error = getaddrinfo(send_addr, send_port, &hints, &send_res);
   if (error != 0) errx(1, "%s", gai_strerror(error));
   send_res->ai_family = AF_INET6;
   send_s = socket(send_res->ai_family, send_res->ai_socktype,
                   send_res->ai_protocol);
   if (send_s < 0) err(1, "socket");

// Add for MC support
   sin6 = (struct sockaddr_in6 *)send_res->ai_addr;
   if(IN6_IS_ADDR_MULTICAST(&(sin6->sin6_addr))) {
       if ( (ifindex = if_nametoindex(out_if)) == 0 ){
           err(1, "socket-MC");
       }
       error = setsockopt(send_s, IPPROTO_IPV6, IPV6_MULTICAST_IF,
                          &ifindex, sizeof(ifindex));
       if (error < 0){
           err(1, "socket-MC");
       }
   }

}
send_v6_udp()
{
   int len,cc,i;
   char buf[2000];

   for( i=0; i<2000 ; i++ ){
       buf[i]='a';
   }
   if(  1501 > out_packet_size ){
       cc = out_packet_size ;
   }else{
       cc = 1500;
   }
   printf("Let's send %d length packet to %s\n",cc,send_addr);
   while(1){
       len = sendto(send_s, buf, cc, 0, send_res->ai_addr,
send_res->ai_addrlen);
       sleep(1);
   }
}

recv_v6_udp()
{
   int recv_s;
   struct addrinfo hints, *res;
   int error;
   int len,cc,ccout;
   char buf[2000];
   FILE *outfp=stdout;
   int fromlen;
   struct sockaddr_in6 from6;

   memset(&hints, 0, sizeof(hints));
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_DGRAM;
   error = getaddrinfo(recv_addr, recv_port, &hints, &res);
   if (error != 0) errx(1, "%s", gai_strerror(error));
   res->ai_family = AF_INET6;
   recv_s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
   if (recv_s < 0) err(1, "socket");

   while(1){
       cc = recvfrom(recv_s, (void *)buf, sizeof(buf), 0,
                     (struct sockaddr *)&from6, &fromlen);
       if (cc < 0) {
           warn("recvfrom");
           continue;
       }
       if ( only_in == 0 ){
           len = sendto(send_s, buf, cc, 0, send_res->ai_addr,
                        send_res->ai_addrlen);
       } else {
           if ((ccout = fwrite(buf, cc, 1, outfp)) < 1)
               close(recv_s);
       }

   }
}
-------------


More information about the freebsd-net mailing list