Added UDP lite support for sockets

This commit is contained in:
goldsimon 2007-06-11 18:43:16 +00:00
parent 2f293d53ba
commit 046a270156
5 changed files with 117 additions and 5 deletions

View File

@ -19,6 +19,9 @@ HISTORY
++ New features: ++ New features:
2007-06-11 Simon Goldschmidt
* sockets.c, sockets.h: Added UDP lite support for sockets
2007-06-10 Simon Goldschmidt 2007-06-10 Simon Goldschmidt
* udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled * udp.h, opt.h, api_msg.c, ip.c, udp.c: Included switch LWIP_UDPLITE (enabled
by default) to switch off UDP-Lite support if not needed (reduces udp.c code by default) to switch off UDP-Lite support if not needed (reduces udp.c code

View File

@ -610,7 +610,8 @@ lwip_socket(int domain, int type, int protocol)
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break; break;
case SOCK_DGRAM: case SOCK_DGRAM:
conn = netconn_new_with_callback(NETCONN_UDP, event_callback); conn = netconn_new_with_callback( (protocol == IPPROTO_UDPLITE) ?
NETCONN_UDPLITE : NETCONN_UDP, event_callback);
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_socket(%s, SOCK_DGRAM, %d) = ",
domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol)); domain == PF_INET ? "PF_INET" : "UNKNOWN", protocol));
break; break;
@ -1057,6 +1058,7 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl
} /* switch (optname) */ } /* switch (optname) */
break; break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */ /* Level: IPPROTO_TCP */
case IPPROTO_TCP: case IPPROTO_TCP:
if (*optlen < sizeof(int)) { if (*optlen < sizeof(int)) {
@ -1082,9 +1084,33 @@ int lwip_getsockopt(int s, int level, int optname, void *optval, socklen_t *optl
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_TCP, UNIMPL: optname=0x%x, ..)\n",
s, optname)); s, optname));
err = ENOPROTOOPT; err = ENOPROTOOPT;
} /* switch (optname */ } /* switch (optname) */
break;
#endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
if (*optlen < sizeof(int)) {
err = EINVAL;
break;
}
/* If this is no UDP lite socket, ignore any options. */
if (sock->conn->type != NETCONN_UDPLITE)
return 0;
switch (optname) {
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
break; break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_UDP && LWIP_UDPLITE*/
/* UNDEFINED LEVEL */ /* UNDEFINED LEVEL */
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
@ -1208,6 +1234,7 @@ static void lwip_getsockopt_internal(void *arg)
} /* switch (optname) */ } /* switch (optname) */
break; break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */ /* Level: IPPROTO_TCP */
case IPPROTO_TCP: case IPPROTO_TCP:
switch (optname) { switch (optname) {
@ -1242,6 +1269,24 @@ static void lwip_getsockopt_internal(void *arg)
} /* switch (optname) */ } /* switch (optname) */
break; break;
#endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
switch (optname) {
case UDPLITE_SEND_CSCOV:
*(int*)optval = sock->conn->pcb.udp->chksum_len_tx;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) = %d\n",
s, (*(int*)optval)) );
break;
case UDPLITE_RECV_CSCOV:
*(int*)optval = sock->conn->pcb.udp->chksum_len_rx;
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_getsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) = %d\n",
s, (*(int*)optval)) );
break;
} /* switch (optname) */
break;
#endif /* LWIP_UDP */
} /* switch (level) */ } /* switch (level) */
sys_mbox_post(sock->conn->mbox, NULL); sys_mbox_post(sock->conn->mbox, NULL);
} }
@ -1332,6 +1377,7 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t
} /* switch (optname) */ } /* switch (optname) */
break; break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */ /* Level: IPPROTO_TCP */
case IPPROTO_TCP: case IPPROTO_TCP:
if (optlen < sizeof(int)) { if (optlen < sizeof(int)) {
@ -1359,7 +1405,31 @@ int lwip_setsockopt(int s, int level, int optname, const void *optval, socklen_t
err = ENOPROTOOPT; err = ENOPROTOOPT;
} /* switch (optname) */ } /* switch (optname) */
break; break;
#endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
if (optlen < sizeof(int)) {
err = EINVAL;
break;
}
/* If this is no UDP lite socket, ignore any options. */
if (sock->conn->type != NETCONN_UDPLITE)
return 0;
switch (optname) {
case UDPLITE_SEND_CSCOV:
case UDPLITE_RECV_CSCOV:
break;
default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UNIMPL: optname=0x%x, ..)\n",
s, optname));
err = ENOPROTOOPT;
} /* switch (optname) */
break;
#endif /* LWIP_UDP && LWIP_UDPLITE */
/* UNDEFINED LEVEL */ /* UNDEFINED LEVEL */
default: default:
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n", LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, level=0x%x, UNIMPL: optname=0x%x, ..)\n",
@ -1481,6 +1551,7 @@ static void lwip_setsockopt_internal(void *arg)
} /* switch (optname) */ } /* switch (optname) */
break; break;
#if LWIP_TCP
/* Level: IPPROTO_TCP */ /* Level: IPPROTO_TCP */
case IPPROTO_TCP: case IPPROTO_TCP:
switch (optname) { switch (optname) {
@ -1519,6 +1590,34 @@ static void lwip_setsockopt_internal(void *arg)
} /* switch (optname) */ } /* switch (optname) */
break; break;
#endif /* LWIP_TCP*/
#if LWIP_UDP && LWIP_UDPLITE
/* Level: IPPROTO_UDPLITE */
case IPPROTO_UDPLITE:
switch (optname) {
case UDPLITE_SEND_CSCOV:
if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
/* don't allow illegal values! */
sock->conn->pcb.udp->chksum_len_tx = 8;
} else {
sock->conn->pcb.udp->chksum_len_tx = *(int*)optval;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_SEND_CSCOV) -> %lu\n",
s, (*(int*)optval)) );
break;
case UDPLITE_RECV_CSCOV:
if ((*(int*)optval != 0) && (*(int*)optval < 8)) {
/* don't allow illegal values! */
sock->conn->pcb.udp->chksum_len_rx = 8;
} else {
sock->conn->pcb.udp->chksum_len_rx = *(int*)optval;
}
LWIP_DEBUGF(SOCKETS_DEBUG, ("lwip_setsockopt(%d, IPPROTO_UDPLITE, UDPLITE_RECV_CSCOV) -> %lu\n",
s, (*(int*)optval)) );
break;
} /* switch (optname) */
break;
#endif /* LWIP_UDP */
} /* switch (level) */ } /* switch (level) */
sys_mbox_post(sock->conn->mbox, NULL); sys_mbox_post(sock->conn->mbox, NULL);
} }

View File

@ -414,7 +414,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
u16_t chklen; u16_t chklen;
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE packet length %"U16_F"\n", q->tot_len));
/* set UDP message length in UDP header */ /* set UDP message length in UDP header */
chklen = pcb->chksum_len; chklen = pcb->chksum_len_tx;
if (chklen < sizeof(struct udp_hdr)) { if (chklen < sizeof(struct udp_hdr)) {
if (chklen != 0) { if (chklen != 0) {
LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen)); LWIP_DEBUGF(UDP_DEBUG, ("udp_send: UDP LITE pcb->chksum_len is illegal: %"U16_F"\n", chklen));
@ -431,7 +431,7 @@ udp_send(struct udp_pcb *pcb, struct pbuf *p)
/* calculate checksum */ /* calculate checksum */
#if CHECKSUM_GEN_UDP #if CHECKSUM_GEN_UDP
udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip), udphdr->chksum = inet_chksum_pseudo(q, src_ip, &(pcb->remote_ip),
IP_PROTO_UDP, pcb->chksum_len); IP_PROTO_UDP, chklen);
/* chksum zero must become 0xffff, as zero means 'no checksum' */ /* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) if (udphdr->chksum == 0x0000)
udphdr->chksum = 0xffff; udphdr->chksum = 0xffff;

View File

@ -118,6 +118,7 @@ struct linger {
#define IPPROTO_IP 0 #define IPPROTO_IP 0
#define IPPROTO_TCP 6 #define IPPROTO_TCP 6
#define IPPROTO_UDP 17 #define IPPROTO_UDP 17
#define IPPROTO_UDPLITE 136
#define INADDR_ANY 0 #define INADDR_ANY 0
#define INADDR_BROADCAST 0xffffffff #define INADDR_BROADCAST 0xffffffff
@ -143,6 +144,15 @@ struct linger {
#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ #define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */
#endif /* LWIP_TCP */ #endif /* LWIP_TCP */
#if LWIP_UDP && LWIP_UDPLITE
/*
* Options for level IPPROTO_UDPLITE
*/
#define UDPLITE_SEND_CSCOV 0x01 /* sender checksum coverage */
#define UDPLITE_RECV_CSCOV 0x02 /* minimal receiver checksum coverage */
#endif
#if LWIP_IGMP #if LWIP_IGMP
/* /*
* Options and types for UDP multicast traffic handling * Options and types for UDP multicast traffic handling

View File

@ -70,7 +70,7 @@ struct udp_pcb {
#if LWIP_UDPLITE #if LWIP_UDPLITE
/* used for UDP_LITE only */ /* used for UDP_LITE only */
u16_t chksum_len; u16_t chksum_len_rx, chksum_len_tx;
#endif /* LWIP_UDPLITE */ #endif /* LWIP_UDPLITE */
/* addr and port are in same byte order as in the pcb */ /* addr and port are in same byte order as in the pcb */