Hi,

I'm trying to install the latest version of heartbeat (linux-ha), which unfortunately is not available from the ports tree yet. Setup is two boxes running (5.4-STABLE FreeBSD from Oct 17 2005) both connected to a hub with lnc NICs on a private 10.0.0.0/24 subnet (actually its only a 'simulated hub' provided by VMWare if this matters).

After some initial struggles configuration, build and installations works as expected - but now the most basic parts of this application won't work anymore. When trying to use UDP broadcast messages for the heartbeat it would error out with "Message too long" for packets larger than 1472 bytes, in other words as soon as fragmentation of the package would be necessary (MTU is 1500).

I received a code snippet from the heartbeat developers to isolate the problem (create sender and receiver socket, send broadcast packets of a certain size). To rule out VMware as the basic problem I tried real boxes but the problem persists.

Is there any size restriction for UDP broadcast messages?
Is there anything which prevents UDP broadcast from being fragmented?

I searched RFCs, man pages for socket, setsockopt, ioctl, sendto and other places but did not find anything that could explain the behaviour (which seems to be no problem on other OS).

Any pointers, comments?

Thanks,
 Michael

N.B:
Code snippet is attached in case somebody cares to take a look - it works fine for me when using "./bcast-test -r -i lnc1 -p 1500" on the receiving box and
"./bcast-test -r -i lnc1 -p XXX" on the sending box for XXX < 1473.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <net/if.h>
#include <errno.h>
#include <sys/ioctl.h>

#define PORT 694
#define MAXBUF 2048

void
usage(int argc, char ** argv)
{
        printf("Usage: %s [-s] [-r] -p packetsize -i eth0/eth1/...\n", argv[0]);
        printf("#default is to receive\n");
        return;
}

int
create_recv_socket(char* ifname)
{
        struct sockaddr_in my_addr;
        int sockfd;
        int one = 1;
        struct ifreq i;


        memset(&my_addr, 0, sizeof(my_addr));
        my_addr.sin_family = AF_INET;
        my_addr.sin_port = htons(PORT);
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

        if (( sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){
                printf("Error getting socket: %s\n", strerror(errno));
                exit(1);
        }

        if (setsockopt( sockfd, SOL_SOCKET,
                        SO_REUSEADDR, (const void*)&one, sizeof(one)) < 0){
                printf("Error setting socket option SO_REUSEADDR: %s\n",
                       strerror(errno));
                exit(1);
        }

        strcpy(i.ifr_name, ifname);

        if (bind(sockfd, (struct sockaddr *) & my_addr, sizeof(struct sockaddr))
            < 0){
                printf("Error binding socket: %s\n", strerror(errno));
                exit(1);
        }

        return sockfd;
}


void
recv_packets(int sockfd, int packetsize)
{
        int bufsize = packetsize + 100;
        char buf[MAXBUF];
        int n;
        struct sockaddr_in theiraddr;
        int len = sizeof(theiraddr);

        while(1){

                memset(buf, 0, MAXBUF);
                if ((n = recvfrom(sockfd, buf, bufsize - 1, 0,
                                  (struct sockaddr*)&theiraddr, &len)) == -1){
                        printf("Error receiving from socket: %s\n", 
strerror(errno));
                        exit(1);
                }
                printf("Message received: (%d bytes)\n%s\n", n, buf);
        }

}

int
create_send_socket(char* ifname)
{
        int sockfd;
        int one = 1;
        struct ifreq i;
        strcpy(i.ifr_name,ifname);

        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) <= 0) {
                printf("Error in getting socket: %s", strerror(errno));
                exit(1);
        }


        if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, (const void*) &one, 
sizeof(one)) == -1)
                {
                        printf("Error setting socket option SO_BROADCAST: 
sockfd =%d , %s\n",
                               sockfd, strerror(errno));
                        close(sockfd);
                        exit(1);
                }

        return sockfd;
}


int
get_baddr(struct sockaddr_in* baddr, char* ifname)
{
        struct ifreq ifr;
        int fd;
        int return_val;

        fd = socket (PF_INET, SOCK_DGRAM, 0);

        if (fd <0) {
                printf("Error opening socket: %s\n", strerror(errno));
                exit(1);
        }

        strcpy (ifr.ifr_name, ifname);

        return_val = ioctl(fd, SIOCGIFBRDADDR, &ifr);
        if (return_val == 0 )
                {
                        if (ifr.ifr_broadaddr.sa_family == AF_INET)
                                {
                                        struct sockaddr_in sin_ptr;
                                        memcpy(&sin_ptr, &ifr.ifr_broadaddr,
                                               sizeof(sin_ptr));
                                        memcpy(&baddr->sin_addr, 
&sin_ptr.sin_addr,
                                               sizeof(baddr->sin_addr));
                                }
                        else
                                {
                                        printf("Wrong family for broadcast 
interface : %s",
                                               strerror(errno));
                                        exit(1);
                                }

                }
        else
                {
                        printf("Get broadcast for interfade failed: %s\n", 
strerror(errno));
                        exit(1);
                }

        baddr->sin_family = AF_INET;
        baddr->sin_port = htons(PORT);

        return 0;
}



void
send_packets(int sockfd, struct sockaddr* addr, int packetsize)
{
        int i;
        char packet[MAXBUF];
        char size[10];
        int ret;

        memset(packet, 'A', packetsize);
        packet[packetsize-1] = '\0';
        sprintf(size, "%d", packetsize);
        strcpy(packet, size);
        packet[strlen(size)] = ' ';

        for ( i = 0; i < 1000; i++)
                {
                        printf("sending packet %d\n", i);
                        if ( (ret = sendto(sockfd, packet, packetsize, 0,addr 
,sizeof(struct sockaddr)))
                             != packetsize)
                                {
                                        printf("Unable to send bcast packets: 
%s\n", strerror(errno));
                                        exit(1);
                                }
                }

}



int
main(int argc, char** argv)
{

        int issender = 0;
        int isrecver = 0;
        int packetsize = 0;
        int c;
        char* ifname;

        while ((c = getopt (argc, argv, "sri:p:")) != -1)
                switch(c)
                        {
                        case 's':
                                issender =1;
                                break;
                        case 'r':
                                isrecver =1;
                                break;
                        case 'i':
                                ifname = optarg;
                                break;
                        case 'p':
                                packetsize = atoi(optarg);
                                break;
                        case '?':
                                printf("unknown options\n");
                                usage(argc, argv);
                                return(1);
                        }

        if (issender && isrecver)
                {
                        printf("sender and recver in one program"
                               "is not supported\n");
                        usage(argc, argv);
                        exit(1);

                }

        if (packetsize == 0)
                {
                        printf("invalid packetsize\n");
                        usage(argc, argv);
                        exit(1);

                }

        if (issender)
                {
                        int send_sockfd = create_send_socket(ifname);

                        struct sockaddr_in baddr;

                        get_baddr(&baddr, ifname);

                        send_packets(send_sockfd,(struct sockaddr*)&baddr, 
packetsize);

                        printf("Sending finished!\n");

                }
        else
                {
                        int recv_sockfd = create_recv_socket(ifname);
                        recv_packets( recv_sockfd, packetsize);
                }

        printf("Program ends successfully!\n");
        return 1;
}
_______________________________________________
freebsd-stable@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-stable
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to