BPF question
Ivo Vachkov
ivo.vachkov at gmail.com
Thu Nov 6 09:54:15 PST 2008
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 at 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
>
More information about the freebsd-net
mailing list