New configuration option LWIP_IGMP to enable IGMP processing. Based on only one filter per all network interfaces. Declare a new function in netif to enable to control the MAC filter (to reduce lwIP traffic processing).

Mace Gael for the upper layers, Steve Reynolds for lower ones...
This commit is contained in:
fbernon 2007-03-11 19:16:38 +00:00
parent bc4b3764fc
commit a24a170b84
11 changed files with 218 additions and 36 deletions

View File

@ -23,6 +23,13 @@ HISTORY
++ New features:
2007-03-11 Frédéric Bernon, Mace Gael, Steve Reynolds
* sockets.h, sockets.c, api.h, api_lib.c, api_msg.h, api_msg.c, igmp.h, igmp.c,
ip.c, netif.h, tcpip.c, opt.h:
New configuration option LWIP_IGMP to enable IGMP processing. Based on only one
filter per all network interfaces. Declare a new function in netif to enable to
control the MAC filter (to reduce lwIP traffic processing).
2007-03-11 Frédéric Bernon
* tcp.h, tcp.c, sockets.c, tcp_out.c, tcp_in.c, opt.h: Keepalive values can
be configured at run time with LWIP_TCP_KEEPALIVE, but don't change this

View File

@ -682,6 +682,37 @@ netconn_close(struct netconn *conn)
return conn->err;
}
#if LWIP_IGMP
err_t
netconn_join_leave_group (struct netconn *conn,
struct ip_addr *multiaddr,
struct ip_addr *interface,
u16_t join_or_leave)
{
struct api_msg msg;
struct ip_addr *ipaddr[2];
if (conn == NULL) {
return ERR_VAL;
}
if (conn->err != ERR_OK) {
return conn->err;
}
msg.type = API_MSG_JOIN_LEAVE;
msg.msg.conn = conn;
ipaddr[0] = multiaddr;
ipaddr[1] = interface;
msg.msg.msg.bc.ipaddr = (struct ip_addr *)ipaddr;
msg.msg.msg.bc.port = join_or_leave;
api_msg_post(&msg);
sys_mbox_fetch(conn->mbox, NULL);
return conn->err;
}
#endif /* LWIP_IGMP */
err_t
netconn_err(struct netconn *conn)
{

View File

@ -36,6 +36,7 @@
#include "lwip/memp.h"
#include "lwip/sys.h"
#include "lwip/tcpip.h"
#include "lwip/igmp.h"
#if LWIP_RAW
static u8_t
@ -788,6 +789,41 @@ do_close(struct api_msg_msg *msg)
}
sys_mbox_post(msg->conn->mbox, NULL);
}
#if LWIP_IGMP
static void
do_join_leave_group(struct api_msg_msg *msg)
{
err_t err = ERR_OK;
if (msg->conn->pcb.tcp != NULL) {
switch (msg->conn->type) {
#if LWIP_RAW
case NETCONN_RAW:
break;
#endif
#if LWIP_UDP
case NETCONN_UDPLITE:
case NETCONN_UDPNOCHKSUM:
case NETCONN_UDP:
switch(msg->msg.bc.port){
case NETCONN_JOIN: err = igmp_joingroup (netif_default, ((struct ip_addr**)(msg->msg.bc.ipaddr))[0]); break;
case NETCONN_LEAVE: err = igmp_leavegroup(netif_default, ((struct ip_addr**)(msg->msg.bc.ipaddr))[0]); break;
}
break;
#endif /* LWIP_UDP */
#if LWIP_TCP
case NETCONN_TCP:
break;
#endif
default:
break;
}
}
msg->conn->err = err;
sys_mbox_post(msg->conn->mbox, NULL);
}
#endif /* LWIP_IGMP */
typedef void (* api_msg_decode)(struct api_msg_msg *msg);
static api_msg_decode decode[API_MSG_MAX] = {
@ -801,7 +837,10 @@ static api_msg_decode decode[API_MSG_MAX] = {
do_send,
do_recv,
do_write,
do_close
do_close,
#if LWIP_IGMP
do_join_leave_group
#endif /* LWIP_IGMP */
};
void
api_msg_input(struct api_msg *msg)

View File

@ -39,7 +39,7 @@
#include "lwip/api.h"
#include "lwip/arch.h"
#include "lwip/sys.h"
#include "lwip/igmp.h"
#include "lwip/sockets.h"
#define NUM_SOCKETS MEMP_NUM_NETCONN
@ -1237,6 +1237,21 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
err = EINVAL;
}
break;
#if LWIP_IGMP
case IP_MULTICAST_TTL:
{ if(( optlen != sizeof(char) ) && ( optlen != sizeof(int) )) //NOTE, some BSD implementation use "int", some others "char"
{ err = EINVAL;
}
break;
}
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{ if( optlen < sizeof(struct ip_mreq) )
{ err = EINVAL;
}
break;
}
#endif /* LWIP_IGMP */
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, UNIMPL: optname=0x%x, ..)\n", s, optname));
err = ENOPROTOOPT;
@ -1328,6 +1343,27 @@ int lwip_setsockopt (int s, int level, int optname, const void *optval, socklen_
sock->conn->pcb.tcp->tos = (u8_t)(*(int*)optval);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_IP, IP_TOS, ..)-> %u\n", s, sock->conn->pcb.tcp->tos));
break;
#if LWIP_IGMP
case IP_MULTICAST_TTL:
{ if (optlen==sizeof(int)) sock->conn->pcb.tcp->ttl = (u8_t)(*(int*) optval);
if (optlen==sizeof(u8_t)) sock->conn->pcb.tcp->ttl = (u8_t)(*(u8_t*)optval);
break;
}
case IP_ADD_MEMBERSHIP:
case IP_DROP_MEMBERSHIP:
{ /* If this is a TCP or a RAW socket, ignore these options. */
if ((sock->conn->type == NETCONN_TCP) || (sock->conn->type == NETCONN_RAW))
{ err = EAFNOSUPPORT;
}
else
{ struct ip_mreq *imr = (struct ip_mreq *)optval;
if (netconn_join_leave_group( sock->conn, (struct ip_addr *)&(imr->imr_multiaddr.s_addr), (struct ip_addr *)&(imr->imr_interface.s_addr), ((optname==IP_ADD_MEMBERSHIP)?NETCONN_JOIN:NETCONN_LEAVE)) < 0)
{ err = EADDRNOTAVAIL;
}
}
break;
}
#endif /* LWIP_IGMP */
} /* switch */
break;

View File

@ -45,6 +45,7 @@
#include "lwip/tcp.h"
#include "lwip/tcpip.h"
#include "lwip/igmp.h"
static void (* tcpip_init_done)(void *arg) = NULL;
static void *tcpip_init_done_arg;
@ -168,6 +169,9 @@ tcpip_thread(void *arg)
sys_timeout(DHCP_COARSE_TIMER_SECS*1000, dhcp_timer_coarse, NULL);
sys_timeout(DHCP_FINE_TIMER_MSECS, dhcp_timer_fine, NULL);
#endif
#if LWIP_IGMP
igmp_init();
#endif
if (tcpip_init_done != NULL) {
tcpip_init_done(tcpip_init_done_arg);

View File

@ -59,6 +59,9 @@
# include "lwip/dhcp.h"
#endif /* LWIP_DHCP */
#if LWIP_IGMP
# include "lwip/igmp.h"
#endif /* LWIP_IGMP */
/**
* Initializes the IP layer.
@ -227,28 +230,44 @@ ip_input(struct pbuf *p, struct netif *inp) {
pbuf_realloc(p, ntohs(IPH_LEN(iphdr)));
/* match packet against an interface, i.e. is this packet for us? */
for (netif = netif_list; netif != NULL; netif = netif->next) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
/* interface is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
{
/* unicast to this interface address? */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
/* or broadcast on this interface network address? */
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
#if LWIP_IGMP
if (ip_addr_ismulticast(&(iphdr->dest)))
{ if (lookfor_group( inp, &(iphdr->dest)))
{ netif = inp;
}
}
}
else
{ netif = NULL;
}
}
else
{
#endif
for (netif = netif_list; netif != NULL; netif = netif->next) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: iphdr->dest 0x%"X32_F" netif->ip_addr 0x%"X32_F" (0x%"X32_F", 0x%"X32_F", 0x%"X32_F")\n",
iphdr->dest.addr, netif->ip_addr.addr,
iphdr->dest.addr & netif->netmask.addr,
netif->ip_addr.addr & netif->netmask.addr,
iphdr->dest.addr & ~(netif->netmask.addr)));
/* interface is up and configured? */
if ((netif_is_up(netif)) && (!ip_addr_isany(&(netif->ip_addr))))
{
/* unicast to this interface address? */
if (ip_addr_cmp(&(iphdr->dest), &(netif->ip_addr)) ||
/* or broadcast on this interface network address? */
ip_addr_isbroadcast(&(iphdr->dest), netif)) {
LWIP_DEBUGF(IP_DEBUG, ("ip_input: packet accepted on interface %c%c\n",
netif->name[0], netif->name[1]));
/* break out of for loop */
break;
}
}
}
#if LWIP_IGMP
}
#endif
#if LWIP_DHCP
/* Pass DHCP messages regardless of destination address. DHCP traffic is addressed
* using link layer addressing (such as Ethernet MAC) so we must not filter on IP.
@ -310,7 +329,13 @@ ip_input(struct pbuf *p, struct netif *inp) {
}
#if IP_OPTIONS == 0 /* no support for IP options in the IP header? */
#if LWIP_IGMP
/* there is an extra "router alert" option in IGMP messages which we allow for but do not police */
if((iphdrlen > IP_HLEN && (IPH_PROTO(iphdr) != IP_PROTO_IGMP)) {
#else
if (iphdrlen > IP_HLEN) {
#endif
LWIP_DEBUGF(IP_DEBUG | 2, ("IP packet dropped since there were IP options (while IP_OPTIONS == 0).\n"));
pbuf_free(p);
IP_STATS_INC(ip.opterr);
@ -349,6 +374,11 @@ ip_input(struct pbuf *p, struct netif *inp) {
snmp_inc_ipindelivers();
icmp_input(p, inp);
break;
#if LWIP_IGMP
case IP_PROTO_IGMP:
igmp_input(p,inp,&(iphdr->dest));
break;
#endif
default:
/* send ICMP destination protocol unreachable unless is was a broadcast */
if (!ip_addr_isbroadcast(&(iphdr->dest), inp) &&

View File

@ -71,6 +71,13 @@ enum netconn_evt {
NETCONN_EVT_SENDMINUS
};
#if LWIP_IGMP
enum netconn_igmp {
NETCONN_JOIN,
NETCONN_LEAVE
};
#endif /* LWIP_IGMP */
struct netbuf {
struct pbuf *p, *ptr;
struct ip_addr *fromaddr;
@ -155,6 +162,13 @@ err_t netconn_write (struct netconn *conn,
u8_t copy);
err_t netconn_close (struct netconn *conn);
#if LWIP_IGMP
err_t netconn_join_leave_group (struct netconn *conn,
struct ip_addr *multiaddr,
struct ip_addr *interface,
u16_t join_or_leave);
#endif /* LWIP_IGMP */
err_t netconn_err (struct netconn *conn);
#endif /* __LWIP_API_H__ */

View File

@ -59,7 +59,11 @@ enum api_msg_type {
API_MSG_WRITE,
API_MSG_CLOSE,
#if LWIP_IGMP
API_MSG_JOIN_LEAVE,
#endif /* LWIP_IGMP */
API_MSG_MAX
};

View File

@ -126,6 +126,10 @@ struct netif {
u32_t ifoutnucastpkts;
u32_t ifoutdiscards;
#endif
#if LWIP_IGMP
/* This function could be called to add or delete a entry in the multicast filter table of the ethernet MAC.*/
err_t (*igmp_mac_filter)( struct netif *netif, struct ip_addr *group, u8_t action);
#endif
};
/** The list of network interfaces. */

View File

@ -52,6 +52,7 @@
#ifndef NO_SYS
#define NO_SYS 0
#endif
/* ---------- Memory options ---------- */
#ifndef MEM_LIBC_MALLOC
#define MEM_LIBC_MALLOC 0
@ -162,10 +163,7 @@ a lot of data that needs to be copied, this should be set high. */
#define PBUF_LINK_HLEN 14
#endif
/* ---------- ARP options ---------- */
/** Number of active hardware address, IP address pairs cached */
#ifndef ARP_TABLE_SIZE
#define ARP_TABLE_SIZE 10
@ -270,13 +268,11 @@ a lot of data that needs to be copied, this should be set high. */
#endif
/* ---------- ICMP options ---------- */
#ifndef ICMP_TTL
#define ICMP_TTL (IP_DEFAULT_TTL)
#endif
/* ---------- RAW options ---------- */
/* ---------- RAW options ----------- */
#ifndef LWIP_RAW
#define LWIP_RAW 1
#endif
@ -286,7 +282,6 @@ a lot of data that needs to be copied, this should be set high. */
#endif
/* ---------- DHCP options ---------- */
#ifndef LWIP_DHCP
#define LWIP_DHCP 0
#endif
@ -317,6 +312,11 @@ a lot of data that needs to be copied, this should be set high. */
#define SNMP_PRIVATE_MIB 0
#endif
/* ---------- IGMP options ---------- */
#ifndef LWIP_IGMP
#define LWIP_IGMP 0
#endif
/* ---------- UDP options ---------- */
#ifndef LWIP_UDP
#define LWIP_UDP 1
@ -516,7 +516,6 @@ a lot of data that needs to be copied, this should be set high. */
#endif /* LWIP_STATS */
/* ---------- PPP options ---------- */
#ifndef PPP_SUPPORT
#define PPP_SUPPORT 0 /* Set for PPP */
#endif
@ -764,5 +763,3 @@ a lot of data that needs to be copied, this should be set high. */
#endif /* __LWIP_OPT_H__ */

View File

@ -123,10 +123,26 @@ struct linger {
/*
* Options for level IPPROTO_IP
*/
#define IP_TOS 1
#define IP_TTL 2
#define IP_TOS 1
#define IP_TTL 2
#ifdef LWIP_IGMP
/*
* Options and types for UDP multicast traffic handling
*/
#define IP_ADD_MEMBERSHIP 3
#define IP_DROP_MEMBERSHIP 4
#define IP_MULTICAST_TTL 5
#define IP_MULTICAST_IF 6
#define IP_MULTICAST_LOOP 7
typedef struct ip_mreq {
struct in_addr imr_multiaddr; /* IP multicast address of group */
struct in_addr imr_interface; /* local IP address of interface */
} ip_mreq;
#endif /* LWIP_IGMP */
#define IPTOS_TOS_MASK 0x1E
#define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK)
#define IPTOS_LOWDELAY 0x10