Date: Thu, 6 Nov 2008 19:54:13 +0200 From: "Ivo Vachkov" <ivo.vachkov@gmail.com> To: "Robert Watson" <rwatson@freebsd.org> Cc: FreeBSD Net <freebsd-net@freebsd.org> Subject: Re: BPF question Message-ID: <f85d6aa70811060954t1f021ca6mecc081de876b445b@mail.gmail.com> In-Reply-To: <alpine.BSF.1.10.0811061705150.19388@fledge.watson.org> References: <f85d6aa70811060750x7809288dvdb0cf683a50dcfd2@mail.gmail.com> <alpine.BSF.1.10.0811061705150.19388@fledge.watson.org>
next in thread | previous in thread | raw e-mail | index | archive | help
I use following code: /* Send Announce Packet */ int zc_freebsd_sendannounce(int fd, unsigned char *mac, int zc_addr) { unsigned char *announce = NULL; int i = 0; unsigned int packet_len = 0; struct ether_header *eth_hdr = NULL; struct ether_arp *eth_arp = NULL; if (mac == NULL || zc_addr == 0 || zc_addr == -1) return -1; packet_len = sizeof(struct ether_header) + (sizeof(struct ether_arp) >= ETHER_PAYLOAD ? sizeof(struct ether_arp) : ETHER_PAYLOAD); /* Allocate announce packet */ if ((announce = malloc(packet_len)) == NULL) return -1; memset(announce, 0, packet_len); /* Populate Announce Packet * * eth_hdr * saddr - iface mac * daddr - ff:ff:ff:ff:ff:ff * type = ETHERTYPE_ARP * * eth_arp - ARP REQUEST * sender hw addr - iface mac * sender ip addr - zc_addr * target hw addr - 00:00:00:00:00:00 * target ip addr - zc_addr */ eth_hdr = (struct ether_header *)announce; eth_arp = (struct ether_arp *)((char *)eth_hdr + sizeof(struct ether_header)); memcpy(eth_hdr->ether_dhost, eth_bcast_addr, ETHER_ADDR_LEN); memcpy(eth_hdr->ether_shost, mac, ETHER_ADDR_LEN); eth_hdr->ether_type = htons(ETHERTYPE_ARP); eth_arp->arp_hrd = htons(ARPHRD_ETHER); eth_arp->arp_pro = htons(ETHERTYPE_IP); eth_arp->arp_hln = ETHER_ADDR_LEN; eth_arp->arp_pln = IP_ADDR_LEN; eth_arp->arp_op = htons(ARPOP_REQUEST); memcpy(eth_arp->arp_sha, mac, ETHER_ADDR_LEN); memcpy(eth_arp->arp_spa, &zc_addr, IP_ADDR_LEN); memcpy(eth_arp->arp_tha, eth_null_addr, ETHER_ADDR_LEN); memcpy(eth_arp->arp_tpa, &zc_addr, IP_ADDR_LEN); /* Send packet over the wire */ if ((i = write(fd, announce, packet_len)) < 0) { free(announce); return -1; } free(announce); return 0; } and later in my code i call this function in a loop: for (i = 0; i < ANNOUNCE_NUM; i++) { printf("ANNOUNCE ...\n"); fflush(stdout); /* Get initial time */ if (clock_gettime(CLOCK_REALTIME, &ts0) < 0) { perror("clock_gettime"); return -1; } /* Send Announce Packet */ if (zc_freebsd_sendannounce(bpf_fd, mac, zc_addr) < 0) { printf("zc_freebsd_sendannounce(): error\n"); return -1; } /* Possibly check for conflicts here */ /* Get time after select() */ if (clock_gettime(CLOCK_REALTIME, &ts1) < 0) { perror("clock_gettime"); return -1; } printf("ts0.sec |%ld|, ts0.nsec |%ld|\n", ts0.tv_sec, ts0.tv_nsec); fflush(stdout); printf("ts1.sec |%ld|, ts1.nsec |%ld|\n", ts1.tv_sec, ts1.tv_nsec); fflush(stdout); /* wait ANNOUNCE_INTERVAL or the rest of it */ ts0.tv_sec = ANNOUNCE_INTERVAL - (ts1.tv_sec - ts0.tv_sec) >= 0 ? ANNOUNCE_INTERVAL - (ts1.tv_sec - ts0.tv_sec) : 0; ts0.tv_nsec = ((ANNOUNCE_INTERVAL - ts0.tv_sec) * 1000000000) - (ts1.tv_nsec - ts0.tv_nsec) >= 0 ? ((ANNOUNCE_INTERVAL - ts0.tv_sec) * 1000000000) - (ts1.tv_nsec - ts0.tv_nsec) : 0; nanosleep(&ts0, NULL); } /* ANNOUNCE_NUM for() */ >From the two printf()'s above i see the nanosleep() is effective. However, when I check the packet flow with Wireshark (on the same host where this code is running) I see the announce packets timed only miliseconds away from one another. Could this be an issue with Wireshark ?! Right now I have only one computer to work on, but i'll test the timing from another computer asap. P.S. I'm implementing part of RFC3927 (ZeroConf) as part of a bigger project On Thu, Nov 6, 2008 at 7:06 PM, Robert Watson <rwatson@freebsd.org> wrote: > > On Thu, 6 Nov 2008, Ivo Vachkov wrote: > >> I am using simple write() calls to send packets over BPF file descriptor. >> The BPF file descriptor is in buffered read mode (I assume this is the >> default and I do not set it explicitly). From what I see my write() calls >> are somewhat buffered. Since timing is relatively important for my project >> I'd like to ask if there is a way "flush" the write buffer. Setting O_DIRECT >> flag on the file descriptor doesn't seem to have any effect. > > The write(2) system call does no buffering in userspace (unlike, say, > fwrite(3)), and when you write to a BPF device it essentially goes straight > into the network interface output queue, so there should be no need for a > flush mechanism. Could you describe the buffering effect you're seeing a > bit more? > > Robert N M Watson > Computer Laboratory > University of Cambridge >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?f85d6aa70811060954t1f021ca6mecc081de876b445b>