From be7897523d42915910bb5f1828cbe5cb1d6ed8cd Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 1 Jun 2005 22:22:14 +0000 Subject: [PATCH] IGMP protocol now uses the generic background protocol mechanism. --- src/core/nic.c | 159 +--------------------------------------- src/include/etherboot.h | 13 ---- src/include/igmp.h | 33 +++++++-- src/proto/igmp.c | 10 ++- 4 files changed, 37 insertions(+), 178 deletions(-) diff --git a/src/core/nic.c b/src/core/nic.c index 5b857fdd..ebe69e83 100644 --- a/src/core/nic.c +++ b/src/core/nic.c @@ -21,13 +21,10 @@ Literature dealing with the network protocols: #include "resolv.h" #include "dev.h" #include "nic.h" +#include "background.h" #include "elf.h" /* FOR EM_CURRENT */ struct arptable_t arptable[MAX_ARP]; -#if MULTICAST_LEVEL2 -unsigned long last_igmpv1 = 0; -struct igmptable_t igmptable[MAX_IGMP]; -#endif /* Put rom_info in .nocompress section so romprefix.S can write to it */ struct rom_info rom __attribute__ ((section (".text16.nocompress"))) = {0,0}; static unsigned long netmask; @@ -827,140 +824,6 @@ uint16_t tcpudpchksum(struct iphdr *ip) return checksum; } -#ifdef MULTICAST_LEVEL2 -static void send_igmp_reports(unsigned long now) -{ - int i; - for(i = 0; i < MAX_IGMP; i++) { - if (igmptable[i].time && (now >= igmptable[i].time)) { - struct igmp_ip_t igmp; - igmp.router_alert[0] = 0x94; - igmp.router_alert[1] = 0x04; - igmp.router_alert[2] = 0; - igmp.router_alert[3] = 0; - build_ip_hdr(igmptable[i].group.s_addr, - 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp); - igmp.igmp.type = IGMPv2_REPORT; - if (last_igmpv1 && - (now < last_igmpv1 + IGMPv1_ROUTER_PRESENT_TIMEOUT)) { - igmp.igmp.type = IGMPv1_REPORT; - } - igmp.igmp.response_time = 0; - igmp.igmp.chksum = 0; - igmp.igmp.group.s_addr = igmptable[i].group.s_addr; - igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp.igmp)); - ip_transmit(sizeof(igmp), &igmp); -#ifdef MDEBUG - printf("Sent IGMP report to: %@\n", igmp.igmp.group.s_addr); -#endif - /* Don't send another igmp report until asked */ - igmptable[i].time = 0; - } - } -} - -static void process_igmp(struct iphdr *ip, unsigned long now) -{ - struct igmp *igmp; - int i; - unsigned iplen; - if (!ip || (ip->protocol == IP_IGMP) || - (nic.packetlen < sizeof(struct iphdr) + sizeof(struct igmp))) { - return; - } - iplen = (ip->verhdrlen & 0xf)*4; - igmp = (struct igmp *)&nic.packet[sizeof(struct iphdr)]; - if (ipchksum(igmp, ntohs(ip->len) - iplen) != 0) - return; - if ((igmp->type == IGMP_QUERY) && - (ip->dest.s_addr == htonl(GROUP_ALL_HOSTS))) { - unsigned long interval = IGMP_INTERVAL; - if (igmp->response_time == 0) { - last_igmpv1 = now; - } else { - interval = (igmp->response_time * TICKS_PER_SEC)/10; - } - -#ifdef MDEBUG - printf("Received IGMP query for: %@\n", igmp->group.s_addr); -#endif - for(i = 0; i < MAX_IGMP; i++) { - uint32_t group = igmptable[i].group.s_addr; - if ((group == 0) || (group == igmp->group.s_addr)) { - unsigned long time; - time = currticks() + rfc1112_sleep_interval(interval, 0); - if (time < igmptable[i].time) { - igmptable[i].time = time; - } - } - } - } - if (((igmp->type == IGMPv1_REPORT) || (igmp->type == IGMPv2_REPORT)) && - (ip->dest.s_addr == igmp->group.s_addr)) { -#ifdef MDEBUG - printf("Received IGMP report for: %@\n", igmp->group.s_addr); -#endif - for(i = 0; i < MAX_IGMP; i++) { - if ((igmptable[i].group.s_addr == igmp->group.s_addr) && - igmptable[i].time != 0) { - igmptable[i].time = 0; - } - } - } -} - -void leave_group(int slot) -{ - /* Be very stupid and always send a leave group message if - * I have subscribed. Imperfect but it is standards - * compliant, easy and reliable to implement. - * - * The optimal group leave method is to only send leave when, - * we were the last host to respond to a query on this group, - * and igmpv1 compatibility is not enabled. - */ - if (igmptable[slot].group.s_addr) { - struct igmp_ip_t igmp; - igmp.router_alert[0] = 0x94; - igmp.router_alert[1] = 0x04; - igmp.router_alert[2] = 0; - igmp.router_alert[3] = 0; - build_ip_hdr(htonl(GROUP_ALL_HOSTS), - 1, IP_IGMP, sizeof(igmp.router_alert), sizeof(igmp), &igmp); - igmp.igmp.type = IGMP_LEAVE; - igmp.igmp.response_time = 0; - igmp.igmp.chksum = 0; - igmp.igmp.group.s_addr = igmptable[slot].group.s_addr; - igmp.igmp.chksum = ipchksum(&igmp.igmp, sizeof(igmp)); - ip_transmit(sizeof(igmp), &igmp); -#ifdef MDEBUG - printf("Sent IGMP leave for: %@\n", igmp.igmp.group.s_addr); -#endif - } - memset(&igmptable[slot], 0, sizeof(igmptable[0])); -} - -void join_group(int slot, unsigned long group) -{ - /* I have already joined */ - if (igmptable[slot].group.s_addr == group) - return; - if (igmptable[slot].group.s_addr) { - leave_group(slot); - } - /* Only join a group if we are given a multicast ip, this way - * code can be given a non-multicast (broadcast or unicast ip) - * and still work... - */ - if ((group & htonl(MULTICAST_MASK)) == htonl(MULTICAST_NETWORK)) { - igmptable[slot].group.s_addr = group; - igmptable[slot].time = currticks(); - } -} -#else -#define send_igmp_reports(now) do {} while(0) -#define process_igmp(ip, now) do {} while(0) -#endif #include "proto_eth_slow.c" @@ -985,8 +848,8 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) */ for (;;) { now = currticks(); + background_send(now); send_eth_slow_reports(now); - send_igmp_reports(now); result = eth_poll(1); if (result == 0) { /* We don't have anything */ @@ -1104,8 +967,8 @@ int await_reply(reply_t reply, int ival, void *ptr, long timeout) #endif /* MDEBUG */ } } + background_process(now, ptype, ip); process_eth_slow(ptype, now); - process_igmp(ip, now); } return(0); } @@ -1297,20 +1160,4 @@ long rfc2131_sleep_interval(long base, int exp) return tmo; } -#ifdef MULTICAST_LEVEL2 -/************************************************************************** -RFC1112_SLEEP_INTERVAL - sleep for expotentially longer times, up to (base << exp) -**************************************************************************/ -long rfc1112_sleep_interval(long base, int exp) -{ - unsigned long divisor, tmo; -#ifdef BACKOFF_LIMIT - if (exp > BACKOFF_LIMIT) - exp = BACKOFF_LIMIT; -#endif - divisor = RAND_MAX/(base << exp); - tmo = random()/divisor; - return tmo; -} -#endif /* MULTICAST_LEVEL_2 */ diff --git a/src/include/etherboot.h b/src/include/etherboot.h index 669ee8b2..7bc52311 100644 --- a/src/include/etherboot.h +++ b/src/include/etherboot.h @@ -130,16 +130,11 @@ enum { MAX_ARP }; -#define IGMP_SERVER 0 -#define MAX_IGMP IGMP_SERVER+1 - #define RARP_REQUEST 3 #define RARP_REPLY 4 #include "in.h" -#define MULTICAST_MASK 0xF0000000 -#define MULTICAST_NETWORK 0xE0000000 /* Helper macros used to identify when DHCP options are valid/invalid in/outside of encapsulation */ #define NON_ENCAP_OPT in_encapsulated_options == 0 && @@ -164,11 +159,6 @@ struct arptable_t { uint8_t node[6]; } PACKED; -struct igmptable_t { - in_addr group; - unsigned long time; -} PACKED; - #define KERNEL_BUF (BOOTP_DATA_ADDR->bootp_reply.bp_file) #define FLOPPY_BOOT_LOCATION 0x7c00 @@ -214,14 +204,11 @@ int tcp_reset(struct iphdr *ip); typedef int (*reply_t)(int ival, void *ptr, unsigned short ptype, struct iphdr *ip, struct udphdr *udp, struct tcphdr *tcp); extern int await_reply P((reply_t reply, int ival, void *ptr, long timeout)); extern int decode_rfc1533 P((unsigned char *, unsigned int, unsigned int, int)); -extern void join_group(int slot, unsigned long group); -extern void leave_group(int slot); #define RAND_MAX 2147483647L extern uint16_t ipchksum P((const void *ip, unsigned long len)); extern uint16_t add_ipchksums P((unsigned long offset, uint16_t sum, uint16_t new)); extern int32_t random P((void)); extern long rfc2131_sleep_interval P((long base, int exp)); -extern long rfc1112_sleep_interval P((long base, int exp)); extern void cleanup P((void)); /* osloader.c */ diff --git a/src/include/igmp.h b/src/include/igmp.h index 2235d6c6..48753eab 100644 --- a/src/include/igmp.h +++ b/src/include/igmp.h @@ -1,5 +1,8 @@ -#ifndef _IGMP_H -#define _IGMP_H +#ifndef IGMP_H +#define IGMP_H + +#include "stdint.h" +#include "in.h" #define IGMP_QUERY 0x11 #define IGMPv1_REPORT 0x12 @@ -7,11 +10,19 @@ #define IGMP_LEAVE 0x17 #define GROUP_ALL_HOSTS 0xe0000001 /* 224.0.0.1 Host byte order */ +#define MULTICAST_MASK 0xf0000000 +#define MULTICAST_NETWORK 0xe0000000 + +enum { + IGMP_SERVER, + MAX_IGMP +}; + struct igmp { - uint8_t type; - uint8_t response_time; - uint16_t chksum; - in_addr group; + uint8_t type; + uint8_t response_time; + uint16_t chksum; + struct in_addr group; } PACKED; struct igmp_ip_t { /* Format of an igmp ip packet */ @@ -20,4 +31,12 @@ struct igmp_ip_t { /* Format of an igmp ip packet */ struct igmp igmp; } PACKED; -#endif /* _IGMP_H */ +struct igmptable_t { + struct in_addr group; + unsigned long time; +} PACKED; + +extern void join_group ( int slot, unsigned long group ); +extern void leave_group ( int slot ); + +#endif /* IGMP_H */ diff --git a/src/proto/igmp.c b/src/proto/igmp.c index 17dae336..aad530f7 100644 --- a/src/proto/igmp.c +++ b/src/proto/igmp.c @@ -5,6 +5,7 @@ #include "ip.h" #include "igmp.h" +#include "background.h" #include "nic.h" #include "etherboot.h" @@ -56,7 +57,8 @@ static void send_igmp_reports ( unsigned long now ) { } } -static void process_igmp ( struct iphdr *ip, unsigned long now ) { +static void process_igmp ( unsigned long now, unsigned short ptype __unused, + struct iphdr *ip ) { struct igmp *igmp; int i; unsigned iplen; @@ -110,6 +112,11 @@ static void process_igmp ( struct iphdr *ip, unsigned long now ) { } } +static struct background igmp_background __background = { + .send = send_igmp_reports, + .process = process_igmp, +}; + void leave_group ( int slot ) { /* Be very stupid and always send a leave group message if * I have subscribed. Imperfect but it is standards @@ -157,4 +164,3 @@ void join_group ( int slot, unsigned long group ) { igmptable[slot].time = currticks(); } } -