task #12178: hardware checksum capabilities can be configured per netif (use NETIF_SET_CHECKSUM_CTRL() in your netif's init function)

This commit is contained in:
sg 2015-09-01 22:04:15 +02:00
parent c4a1cad81b
commit aa0e41c389
13 changed files with 313 additions and 198 deletions

View File

@ -6,6 +6,10 @@ HISTORY
++ New features:
2015-09-01: Simon Goldschmidt
* task #12178: hardware checksum capabilities can be configured per netif
(use NETIF_SET_CHECKSUM_CTRL() in your netif's init function)
2015-08-30: Simon Goldschmidt
* PBUF_REF with "custom" pbufs is now supported for RX pbufs (see pcapif in
contrib for an example, LWIP_SUPPORT_CUSTOM_PBUF is required)

View File

@ -133,12 +133,14 @@ icmp_input(struct pbuf *p, struct netif *inp)
goto lenerr;
}
#if CHECKSUM_CHECK_ICMP
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP) {
if (inet_chksum_pbuf(p) != 0) {
LWIP_DEBUGF(ICMP_DEBUG, ("icmp_input: checksum failed for received ICMP echo\n"));
pbuf_free(p);
ICMP_STATS_INC(icmp.chkerr);
snmp_inc_icmpinerrors();
return;
}
}
#endif
#if LWIP_ICMP_ECHO_CHECK_INPUT_PBUF_LEN
@ -193,12 +195,19 @@ icmp_input(struct pbuf *p, struct netif *inp)
ip4_addr_copy(iphdr->dest, *ip4_current_src_addr());
ICMPH_TYPE_SET(iecho, ICMP_ER);
#if CHECKSUM_GEN_ICMP
/* adjust the checksum */
if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
} else {
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP) {
/* adjust the checksum */
if (iecho->chksum > PP_HTONS(0xffffU - (ICMP_ECHO << 8))) {
iecho->chksum += PP_HTONS(ICMP_ECHO << 8) + 1;
} else {
iecho->chksum += PP_HTONS(ICMP_ECHO << 8);
}
}
#if LWIP_CHECKSUM_CTRL_PER_NETIF
else {
iecho->chksum = 0;
}
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#else /* CHECKSUM_GEN_ICMP */
iecho->chksum = 0;
#endif /* CHECKSUM_GEN_ICMP */
@ -207,7 +216,9 @@ icmp_input(struct pbuf *p, struct netif *inp)
IPH_TTL_SET(iphdr, ICMP_TTL);
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
}
#endif /* CHECKSUM_GEN_IP */
ICMP_STATS_INC(icmp.xmit);
@ -293,6 +304,7 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
/* we can use the echo header here */
struct icmp_echo_hdr *icmphdr;
ip4_addr_t iphdr_src;
struct netif *netif;
/* ICMP header + IP header + 8 bytes of data */
q = pbuf_alloc(PBUF_IP, sizeof(struct icmp_echo_hdr) + IP_HLEN + ICMP_DEST_UNREACH_DATASIZE,
@ -321,18 +333,23 @@ icmp_send_response(struct pbuf *p, u8_t type, u8_t code)
SMEMCPY((u8_t *)q->payload + sizeof(struct icmp_echo_hdr), (u8_t *)p->payload,
IP_HLEN + ICMP_DEST_UNREACH_DATASIZE);
/* calculate checksum */
icmphdr->chksum = 0;
netif = ip4_route(&iphdr_src);
if (netif != NULL) {
/* calculate checksum */
icmphdr->chksum = 0;
#if CHECKSUM_GEN_ICMP
icmphdr->chksum = inet_chksum(icmphdr, q->len);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP) {
icmphdr->chksum = inet_chksum(icmphdr, q->len);
}
#endif
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
ip4_addr_copy(iphdr_src, iphdr->src);
ip4_output(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP);
ICMP_STATS_INC(icmp.xmit);
/* increase number of messages attempted to send */
snmp_inc_icmpoutmsgs();
/* increase number of destination unreachable messages attempted to send */
snmp_inc_icmpouttimeexcds();
ip4_addr_copy(iphdr_src, iphdr->src);
ip4_output_if(q, NULL, &iphdr_src, ICMP_TTL, 0, IP_PROTO_ICMP, netif);
}
pbuf_free(q);
}

View File

@ -63,8 +63,13 @@
/** Set this to 0 in the rare case of wanting to call an extra function to
* generate the IP checksum (in contrast to calculating it on-the-fly). */
#ifndef LWIP_INLINE_IP_CHKSUM
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define LWIP_INLINE_IP_CHKSUM 0
#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#define LWIP_INLINE_IP_CHKSUM 1
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#endif
#if LWIP_INLINE_IP_CHKSUM && CHECKSUM_GEN_IP
#define CHECKSUM_GEN_IP_INLINE 1
#else
@ -178,7 +183,7 @@ ip4_route(const ip4_addr_t *dest)
if ((netif_default == NULL) || !netif_is_up(netif_default) || !netif_is_link_up(netif_default) ||
ip4_addr_isany_val(*netif_ip4_addr(netif_default))) {
/* No matching netif found an default netif is not usable.
/* No matching netif found and default netif is not usable.
If this is not good enough for you, use LWIP_HOOK_IP4_ROUTE() */
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS, ("ip_route: No route to %"U16_F".%"U16_F".%"U16_F".%"U16_F"\n",
ip4_addr1_16(dest), ip4_addr2_16(dest), ip4_addr3_16(dest), ip4_addr4_16(dest)));
@ -443,16 +448,18 @@ ip4_input(struct pbuf *p, struct netif *inp)
/* verify checksum */
#if CHECKSUM_CHECK_IP
if (inet_chksum(iphdr, iphdr_hlen) != 0) {
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_IP) {
if (inet_chksum(iphdr, iphdr_hlen) != 0) {
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
ip4_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipinhdrerrors();
return ERR_OK;
LWIP_DEBUGF(IP_DEBUG | LWIP_DBG_LEVEL_SERIOUS,
("Checksum (0x%"X16_F") failed, IP packet dropped.\n", inet_chksum(iphdr, iphdr_hlen)));
ip4_debug_print(p);
pbuf_free(p);
IP_STATS_INC(ip.chkerr);
IP_STATS_INC(ip.drop);
snmp_inc_ipinhdrerrors();
return ERR_OK;
}
}
#endif
@ -597,7 +604,7 @@ ip4_input(struct pbuf *p, struct netif *inp)
/* packet consists of multiple fragments? */
if ((IPH_OFFSET(iphdr) & PP_HTONS(IP_OFFMASK | IP_MF)) != 0) {
#if IP_REASSEMBLY /* packet fragment reassembly code present? */
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip_reass()\n",
LWIP_DEBUGF(IP_DEBUG, ("IP packet is a fragment (id=0x%04"X16_F" tot_len=%"U16_F" len=%"U16_F" MF=%"U16_F" offset=%"U16_F"), calling ip4_reass()\n",
ntohs(IPH_ID(iphdr)), p->tot_len, ntohs(IPH_LEN(iphdr)), !!(IPH_OFFSET(iphdr) & PP_HTONS(IP_MF)), (ntohs(IPH_OFFSET(iphdr)) & IP_OFFMASK)*8));
/* reassemble the packet*/
p = ip4_reass(p);
@ -889,12 +896,21 @@ err_t ip4_output_if_opt_src(struct pbuf *p, const ip4_addr_t *src, const ip4_add
chk_sum = (chk_sum >> 16) + (chk_sum & 0xFFFF);
chk_sum = (chk_sum >> 16) + chk_sum;
chk_sum = ~chk_sum;
iphdr->_chksum = (u16_t)chk_sum; /* network order */
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
iphdr->_chksum = (u16_t)chk_sum; /* network order */
}
#if LWIP_CHECKSUM_CTRL_PER_NETIF
else {
IPH_CHKSUM_SET(iphdr, 0);
}
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
#else /* CHECKSUM_GEN_IP_INLINE */
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
#endif
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, ip_hlen));
}
#endif /* CHECKSUM_GEN_IP */
#endif /* CHECKSUM_GEN_IP_INLINE */
} else {
/* IP header already included in p */

View File

@ -320,7 +320,7 @@ ip_reass_dequeue_datagram(struct ip_reassdata *ipr, struct ip_reassdata *prev)
prev->next = ipr->next;
}
/* now we can free the ip_reass struct */
/* now we can free the ip_reassdata struct */
memp_free(MEMP_REASSDATA, ipr);
}
@ -494,7 +494,7 @@ ip4_reass(struct pbuf *p)
fraghdr = (struct ip_hdr*)p->payload;
if ((IPH_HL(fraghdr) * 4) != IP_HLEN) {
LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: IP options currently not supported!\n"));
LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: IP options currently not supported!\n"));
IPFRAG_STATS_INC(ip_frag.err);
goto nullreturn;
}
@ -511,7 +511,7 @@ ip4_reass(struct pbuf *p)
#endif /* IP_REASS_FREE_OLDEST */
{
/* No datagram could be freed and still too many pbufs enqueued */
LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n",
LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: Overflow condition: pbufct=%d, clen=%d, MAX=%d\n",
ip_reass_pbufcount, clen, IP_REASS_MAX_PBUFS));
IPFRAG_STATS_INC(ip_frag.memerr);
/* @todo: send ICMP time exceeded here? */
@ -527,7 +527,7 @@ ip4_reass(struct pbuf *p)
in the reassembly buffer. If so, we proceed with copying the
fragment into the buffer. */
if (IP_ADDRESSES_AND_ID_MATCH(&ipr->iphdr, fraghdr)) {
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip_reass: matching previous fragment ID=%"X16_F"\n",
LWIP_DEBUGF(IP_REASS_DEBUG, ("ip4_reass: matching previous fragment ID=%"X16_F"\n",
ntohs(IPH_ID(fraghdr))));
IPFRAG_STATS_INC(ip_frag.cachehit);
break;
@ -563,7 +563,7 @@ ip4_reass(struct pbuf *p)
ipr->flags |= IP_REASS_FLAG_LASTFRAG;
ipr->datagram_len = offset + len;
LWIP_DEBUGF(IP_REASS_DEBUG,
("ip_reass: last fragment seen, total len %"S16_F"\n",
("ip4_reass: last fragment seen, total len %"S16_F"\n",
ipr->datagram_len));
}
/* find the right place to insert this pbuf */
@ -583,9 +583,11 @@ ip4_reass(struct pbuf *p)
IPH_LEN_SET(fraghdr, htons(ipr->datagram_len));
IPH_OFFSET_SET(fraghdr, 0);
IPH_CHKSUM_SET(fraghdr, 0);
/* @todo: do we need to set calculate the correct checksum? */
/* @todo: do we need to set/calculate the correct checksum? */
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
IF__NETIF_CHECKSUM_ENABLED(ip_current_input_netif(), NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(fraghdr, inet_chksum(fraghdr, IP_HLEN));
}
#endif /* CHECKSUM_GEN_IP */
p = ipr->p;
@ -625,7 +627,7 @@ ip4_reass(struct pbuf *p)
return NULL;
nullreturn:
LWIP_DEBUGF(IP_REASS_DEBUG,("ip_reass: nullreturn\n"));
LWIP_DEBUGF(IP_REASS_DEBUG,("ip4_reass: nullreturn\n"));
IPFRAG_STATS_INC(ip_frag.drop);
pbuf_free(p);
return NULL;
@ -831,7 +833,9 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
IPH_LEN_SET(iphdr, htons(cop + IP_HLEN));
IPH_CHKSUM_SET(iphdr, 0);
#if CHECKSUM_GEN_IP
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_IP) {
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
}
#endif /* CHECKSUM_GEN_IP */
#if IP_FRAG_USES_STATIC_BUF
@ -841,7 +845,7 @@ ip4_frag(struct pbuf *p, struct netif *netif, const ip4_addr_t *dest)
/* This part is ugly: we alloc a RAM based pbuf for
* the link level header for each chunk and then
* free it.A PBUF_ROM style pbuf for which pbuf_header
* free it. A PBUF_ROM style pbuf for which pbuf_header
* worked would make things simpler.
*/
header = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM);

View File

@ -97,13 +97,15 @@ icmp6_input(struct pbuf *p, struct netif *inp)
icmp6hdr = (struct icmp6_hdr *)p->payload;
#if CHECKSUM_CHECK_ICMP6
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
ip6_current_dest_addr()) != 0) {
/* Checksum failed */
pbuf_free(p);
ICMP6_STATS_INC(icmp6.chkerr);
ICMP6_STATS_INC(icmp6.drop);
return;
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_ICMP6) {
if (ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->tot_len, ip6_current_src_addr(),
ip6_current_dest_addr()) != 0) {
/* Checksum failed */
pbuf_free(p);
ICMP6_STATS_INC(icmp6.chkerr);
ICMP6_STATS_INC(icmp6.drop);
return;
}
}
#endif /* CHECKSUM_CHECK_ICMP6 */
@ -180,8 +182,10 @@ icmp6_input(struct pbuf *p, struct netif *inp)
((struct icmp6_echo_hdr *)(r->payload))->type = ICMP6_TYPE_EREP;
((struct icmp6_echo_hdr *)(r->payload))->chksum = 0;
#if CHECKSUM_GEN_ICMP6
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_GEN_ICMP6) {
((struct icmp6_echo_hdr *)(r->payload))->chksum = ip6_chksum_pseudo(r,
IP6_NEXTH_ICMP6, r->tot_len, reply_src, ip6_current_src_addr());
}
#endif /* CHECKSUM_GEN_ICMP6 */
/* Send reply. */
@ -330,8 +334,10 @@ icmp6_send_response(struct pbuf *p, u8_t code, u32_t data, u8_t type)
/* calculate checksum */
icmp6hdr->chksum = 0;
#if CHECKSUM_GEN_ICMP6
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
reply_src, reply_dest);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
icmp6hdr->chksum = ip6_chksum_pseudo(q, IP6_NEXTH_ICMP6, q->tot_len,
reply_src, reply_dest);
}
#endif /* CHECKSUM_GEN_ICMP6 */
ICMP6_STATS_INC(icmp6.xmit);

View File

@ -569,8 +569,10 @@ mld6_send(struct mld_group *group, u8_t type)
ip6_addr_set(&(mld_hdr->multicast_address), &(group->group_address));
#if CHECKSUM_GEN_ICMP6
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
src_addr, &(group->group_address));
IF__NETIF_CHECKSUM_ENABLED(group->netif, NETIF_CHECKSUM_GEN_ICMP6) {
mld_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len,
src_addr, &(group->group_address));
}
#endif /* CHECKSUM_GEN_ICMP6 */
/* Add hop-by-hop headers options: router alert with MLD value. */

View File

@ -878,8 +878,10 @@ nd6_send_ns(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
}
#if CHECKSUM_GEN_ICMP6
ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
target_addr);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
target_addr);
}
#endif /* CHECKSUM_GEN_ICMP6 */
/* Send the packet out. */
@ -954,8 +956,10 @@ nd6_send_na(struct netif * netif, const ip6_addr_t * target_addr, u8_t flags)
}
#if CHECKSUM_GEN_ICMP6
na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
dest_addr);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
dest_addr);
}
#endif /* CHECKSUM_GEN_ICMP6 */
/* Send the packet out. */
@ -1023,8 +1027,10 @@ nd6_send_rs(struct netif * netif)
}
#if CHECKSUM_GEN_ICMP6
rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
&multicast_address);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_ICMP6) {
rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->len, src_addr,
&multicast_address);
}
#endif /* CHECKSUM_GEN_ICMP6 */
/* Send the packet out. */

View File

@ -205,6 +205,7 @@ netif_add(struct netif *netif,
}
netif->output_ip6 = netif_null_output_ip6;
#endif /* LWIP_IPV6 */
NETIF_SET_CHECKSUM_CTRL(netif, NETIF_CHECKSUM_ENABLE_ALL);
netif->flags = 0;
#if LWIP_DHCP
/* netif not under DHCP control by default */

View File

@ -111,9 +111,6 @@ tcp_input(struct pbuf *p, struct netif *inp)
#endif /* SO_REUSE */
u8_t hdrlen;
err_t err;
#if CHECKSUM_CHECK_TCP
u16_t chksum;
#endif /* CHECKSUM_CHECK_TCP */
LWIP_UNUSED_ARG(inp);
@ -147,15 +144,17 @@ tcp_input(struct pbuf *p, struct netif *inp)
}
#if CHECKSUM_CHECK_TCP
/* Verify TCP checksum. */
chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
ip_current_src_addr(), ip_current_dest_addr());
if (chksum != 0) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
chksum));
tcp_debug_print(tcphdr);
TCP_STATS_INC(tcp.chkerr);
goto dropped;
IF__NETIF_CHECKSUM_ENABLED(inp, NETIF_CHECKSUM_CHECK_TCP) {
/* Verify TCP checksum. */
u16_t chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
ip_current_src_addr(), ip_current_dest_addr());
if (chksum != 0) {
LWIP_DEBUGF(TCP_INPUT_DEBUG, ("tcp_input: packet discarded due to failing checksum 0x%04"X16_F"\n",
chksum));
tcp_debug_print(tcphdr);
TCP_STATS_INC(tcp.chkerr);
goto dropped;
}
}
#endif /* CHECKSUM_CHECK_TCP */

View File

@ -898,6 +898,7 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
err_t err;
struct pbuf *p;
u8_t optlen = 0;
struct netif *netif;
#if LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP
struct tcp_hdr *tcphdr;
#endif /* LWIP_TCP_TIMESTAMPS || CHECKSUM_GEN_TCP */
@ -928,19 +929,23 @@ tcp_send_empty_ack(struct tcp_pcb *pcb)
if (pcb->flags & TF_TIMESTAMP) {
tcp_build_timestamp_option(pcb, (u32_t *)(tcphdr + 1));
}
#endif
#if CHECKSUM_GEN_TCP
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
#endif
#if LWIP_NETIF_HWADDRHINT
err = ip_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
IP_PROTO_TCP, &pcb->addr_hint);
#else /* LWIP_NETIF_HWADDRHINT*/
err = ip_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, pcb->tos,
IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
netif = ip_route(PCB_ISIPV6(pcb), &pcb->remote_ip, &pcb->local_ip);
if (netif == NULL) {
err = ERR_RTE;
} else {
#if CHECKSUM_GEN_TCP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
}
#endif
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
err = ip_output_if(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
pcb->ttl, pcb->tos, IP_PROTO_TCP, netif);
NETIF_SET_HWADDRHINT(netif, NULL);
}
pbuf_free(p);
if (err != ERR_OK) {
@ -1128,6 +1133,7 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
err_t err;
u16_t len;
u32_t *opts;
struct netif *netif;
/** @bug Exclude retransmitted segments from this count. */
snmp_inc_tcpoutsegs();
@ -1184,13 +1190,16 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
pcb->rtime = 0;
}
/* If we don't have a local IP address, we get one by
calling ip_route(). */
netif = ip_route(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
if (netif == NULL) {
return ERR_RTE;
}
/* If we don't have a local IP address, we get one from netif */
if (ip_addr_isany(&pcb->local_ip)) {
struct netif *netif;
ip_addr_t *local_ip;
ip_route_get_local_ip(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip, netif, local_ip, &pcb->local_ip);
if ((netif == NULL) || (local_ip == NULL)) {
ip_addr_t *local_ip = ip_netif_get_local_ip(PCB_ISIPV6(pcb), netif,
&pcb->remote_ip, &pcb->local_ip);
if (local_ip == NULL) {
return ERR_RTE;
}
#if !LWIP_IPV4 || !LWIP_IPV6
@ -1216,8 +1225,9 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
seg->p->payload = seg->tcphdr;
seg->tcphdr->chksum = 0;
#if CHECKSUM_GEN_TCP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
#if TCP_CHECKSUM_ON_COPY
{
u32_t acc;
#if TCP_CHECKSUM_ON_COPY_SANITY_CHECK
u16_t chksum_slow = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
@ -1246,22 +1256,18 @@ tcp_output_segment(struct tcp_seg *seg, struct tcp_pcb *pcb)
seg->tcphdr->chksum = chksum_slow;
}
#endif /* TCP_CHECKSUM_ON_COPY_SANITY_CHECK */
}
#else /* TCP_CHECKSUM_ON_COPY */
#if CHECKSUM_GEN_TCP
seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
#endif /* CHECKSUM_GEN_TCP */
seg->tcphdr->chksum = ip_chksum_pseudo(seg->p, IP_PROTO_TCP,
seg->p->tot_len, &pcb->local_ip, &pcb->remote_ip);
#endif /* TCP_CHECKSUM_ON_COPY */
#endif /* CHECKSUM_GEN_TCP */
}
TCP_STATS_INC(tcp.xmit);
#if LWIP_NETIF_HWADDRHINT
err = ip_output_hinted(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip,
pcb->ttl, pcb->tos, IP_PROTO_TCP, &pcb->addr_hint);
#else /* LWIP_NETIF_HWADDRHINT*/
err = ip_output(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
pcb->tos, IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
err = ip_output_if(PCB_ISIPV6(pcb), seg->p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
pcb->tos, IP_PROTO_TCP, netif);
NETIF_SET_HWADDRHINT(netif, NULL);
return err;
}
@ -1292,6 +1298,7 @@ tcp_rst(u32_t seqno, u32_t ackno,
{
struct pbuf *p;
struct tcp_hdr *tcphdr;
struct netif *netif;
p = pbuf_alloc(PBUF_IP, TCP_HLEN, PBUF_RAM);
if (p == NULL) {
LWIP_DEBUGF(TCP_DEBUG, ("tcp_rst: could not allocate memory for pbuf\n"));
@ -1317,12 +1324,17 @@ tcp_rst(u32_t seqno, u32_t ackno,
TCP_STATS_INC(tcp.xmit);
snmp_inc_tcpoutrsts();
netif = ip_route(IP_IS_V6(remote_ip), local_ip, remote_ip);
if (netif != NULL) {
#if CHECKSUM_GEN_TCP
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
local_ip, remote_ip);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
local_ip, remote_ip);
}
#endif
/* Send output with hardcoded TTL/HL since we have no access to the pcb */
ip_output(IP_IS_V6(remote_ip), p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP);
/* Send output with hardcoded TTL/HL since we have no access to the pcb */
ip_output_if(IP_IS_V6(remote_ip), p, local_ip, remote_ip, TCP_TTL, 0, IP_PROTO_TCP, netif);
}
pbuf_free(p);
LWIP_DEBUGF(TCP_RST_DEBUG, ("tcp_rst: seqno %"U32_F" ackno %"U32_F".\n", seqno, ackno));
}
@ -1469,9 +1481,7 @@ tcp_keepalive(struct tcp_pcb *pcb)
{
err_t err;
struct pbuf *p;
#if CHECKSUM_GEN_TCP
struct tcp_hdr *tcphdr;
#endif /* CHECKSUM_GEN_TCP */
struct netif *netif;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: sending KEEPALIVE probe to "));
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
@ -1486,23 +1496,25 @@ tcp_keepalive(struct tcp_pcb *pcb)
("tcp_keepalive: could not allocate memory for pbuf\n"));
return ERR_MEM;
}
netif = ip_route(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
if (netif == NULL) {
err = ERR_RTE;
} else {
#if CHECKSUM_GEN_TCP
tcphdr = (struct tcp_hdr *)p->payload;
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
struct tcp_hdr *tcphdr = (struct tcp_hdr *)p->payload;
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
}
#endif /* CHECKSUM_GEN_TCP */
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
#if LWIP_NETIF_HWADDRHINT
err = ip_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip,
pcb->ttl, 0, IP_PROTO_TCP, &pcb->addr_hint);
#else /* LWIP_NETIF_HWADDRHINT*/
err = ip_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
0, IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
err = ip_output_if(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
0, IP_PROTO_TCP, netif);
NETIF_SET_HWADDRHINT(netif, NULL);
}
pbuf_free(p);
LWIP_DEBUGF(TCP_DEBUG, ("tcp_keepalive: seqno %"U32_F" ackno %"U32_F" err %d.\n",
@ -1528,6 +1540,7 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
struct tcp_seg *seg;
u16_t len;
u8_t is_fin;
struct netif *netif;
LWIP_DEBUGF(TCP_DEBUG, ("tcp_zero_window_probe: sending ZERO WINDOW probe to "));
ip_addr_debug_print(TCP_DEBUG, &pcb->remote_ip);
@ -1571,19 +1584,23 @@ tcp_zero_window_probe(struct tcp_pcb *pcb)
pbuf_copy_partial(seg->p, d, 1, seg->p->tot_len - seg->len);
}
netif = ip_route(PCB_ISIPV6(pcb), &pcb->local_ip, &pcb->remote_ip);
if (netif == NULL) {
err = ERR_RTE;
} else {
#if CHECKSUM_GEN_TCP
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_TCP) {
tcphdr->chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
&pcb->local_ip, &pcb->remote_ip);
}
#endif
TCP_STATS_INC(tcp.xmit);
TCP_STATS_INC(tcp.xmit);
/* Send output to IP */
#if LWIP_NETIF_HWADDRHINT
err = ip_output_hinted(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
0, IP_PROTO_TCP, &pcb->addr_hint);
#else /* LWIP_NETIF_HWADDRHINT*/
err = ip_output(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl, 0, IP_PROTO_TCP);
#endif /* LWIP_NETIF_HWADDRHINT*/
/* Send output to IP */
NETIF_SET_HWADDRHINT(netif, &(pcb->addr_hint));
err = ip_output_if(PCB_ISIPV6(pcb), p, &pcb->local_ip, &pcb->remote_ip, pcb->ttl,
0, IP_PROTO_TCP, netif);
}
pbuf_free(p);

View File

@ -325,34 +325,36 @@ udp_input(struct pbuf *p, struct netif *inp)
if (for_us) {
LWIP_DEBUGF(UDP_DEBUG | LWIP_DBG_TRACE, ("udp_input: calculating checksum\n"));
#if CHECKSUM_CHECK_UDP
IF__NETIF_CHECKSUM_ENABLED(inp, CHECKSUM_CHECK_UDP) {
#if LWIP_UDPLITE
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
/* Do the UDP Lite checksum */
u16_t chklen = ntohs(udphdr->len);
if (chklen < sizeof(struct udp_hdr)) {
if (chklen == 0) {
/* For UDP-Lite, checksum length of 0 means checksum
over the complete packet (See RFC 3828 chap. 3.1) */
chklen = p->tot_len;
} else {
/* At least the UDP-Lite header must be covered by the
checksum! (Again, see RFC 3828 chap. 3.1) */
if (ip_current_header_proto() == IP_PROTO_UDPLITE) {
/* Do the UDP Lite checksum */
u16_t chklen = ntohs(udphdr->len);
if (chklen < sizeof(struct udp_hdr)) {
if (chklen == 0) {
/* For UDP-Lite, checksum length of 0 means checksum
over the complete packet (See RFC 3828 chap. 3.1) */
chklen = p->tot_len;
} else {
/* At least the UDP-Lite header must be covered by the
checksum! (Again, see RFC 3828 chap. 3.1) */
goto chkerr;
}
}
if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE,
p->tot_len, chklen,
ip_current_src_addr(), ip_current_dest_addr()) != 0) {
goto chkerr;
}
}
if (ip_chksum_pseudo_partial(p, IP_PROTO_UDPLITE,
p->tot_len, chklen,
ip_current_src_addr(), ip_current_dest_addr()) != 0) {
goto chkerr;
}
} else
} else
#endif /* LWIP_UDPLITE */
{
if (udphdr->chksum != 0) {
if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len,
ip_current_src_addr(),
ip_current_dest_addr()) != 0) {
goto chkerr;
{
if (udphdr->chksum != 0) {
if (ip_chksum_pseudo(p, IP_PROTO_UDP, p->tot_len,
ip_current_src_addr(),
ip_current_dest_addr()) != 0) {
goto chkerr;
}
}
}
}
@ -804,24 +806,26 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
udphdr->len = htons(chklen_hdr);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
#if LWIP_CHECKSUM_ON_COPY
if (have_chksum) {
chklen = UDP_HLEN;
}
if (have_chksum) {
chklen = UDP_HLEN;
}
#endif /* LWIP_CHECKSUM_ON_COPY */
udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE,
q->tot_len, chklen, src_ip, dst_ip);
udphdr->chksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDPLITE,
q->tot_len, chklen, src_ip, dst_ip);
#if LWIP_CHECKSUM_ON_COPY
if (have_chksum) {
u32_t acc;
acc = udphdr->chksum + (u16_t)~(chksum);
udphdr->chksum = FOLD_U32T(acc);
}
if (have_chksum) {
u32_t acc;
acc = udphdr->chksum + (u16_t)~(chksum);
udphdr->chksum = FOLD_U32T(acc);
}
#endif /* LWIP_CHECKSUM_ON_COPY */
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) {
udphdr->chksum = 0xffff;
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udphdr->chksum == 0x0000) {
udphdr->chksum = 0xffff;
}
}
#endif /* CHECKSUM_GEN_UDP */
@ -833,28 +837,30 @@ udp_sendto_if_src_chksum(struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *d
udphdr->len = htons(q->tot_len);
/* calculate checksum */
#if CHECKSUM_GEN_UDP
/* Checksum is mandatory over IPv6. */
if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
u16_t udpchksum;
IF__NETIF_CHECKSUM_ENABLED(netif, NETIF_CHECKSUM_GEN_UDP) {
/* Checksum is mandatory over IPv6. */
if (PCB_ISIPV6(pcb) || (pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
u16_t udpchksum;
#if LWIP_CHECKSUM_ON_COPY
if (have_chksum) {
u32_t acc;
udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP,
q->tot_len, UDP_HLEN, src_ip, dst_ip);
acc = udpchksum + (u16_t)~(chksum);
udpchksum = FOLD_U32T(acc);
} else
if (have_chksum) {
u32_t acc;
udpchksum = ip_chksum_pseudo_partial(q, IP_PROTO_UDP,
q->tot_len, UDP_HLEN, src_ip, dst_ip);
acc = udpchksum + (u16_t)~(chksum);
udpchksum = FOLD_U32T(acc);
} else
#endif /* LWIP_CHECKSUM_ON_COPY */
{
udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len,
src_ip, dst_ip);
}
{
udpchksum = ip_chksum_pseudo(q, IP_PROTO_UDP, q->tot_len,
src_ip, dst_ip);
}
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udpchksum == 0x0000) {
udpchksum = 0xffff;
/* chksum zero must become 0xffff, as zero means 'no checksum' */
if (udpchksum == 0x0000) {
udpchksum = 0xffff;
}
udphdr->chksum = udpchksum;
}
udphdr->chksum = udpchksum;
}
#endif /* CHECKSUM_GEN_UDP */
ip_proto = IP_PROTO_UDP;

View File

@ -98,6 +98,21 @@ extern "C" {
* Set by the netif driver in its init function. */
#define NETIF_FLAG_MLD6 0x40U
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_CHECKSUM_GEN_IP 0x0001
#define NETIF_CHECKSUM_GEN_UDP 0x0002
#define NETIF_CHECKSUM_GEN_TCP 0x0004
#define NETIF_CHECKSUM_GEN_ICMP 0x0008
#define NETIF_CHECKSUM_GEN_ICMP6 0x0010
#define NETIF_CHECKSUM_CHECK_IP 0x0100
#define NETIF_CHECKSUM_CHECK_UDP 0x0200
#define NETIF_CHECKSUM_CHECK_TCP 0x0400
#define NETIF_CHECKSUM_CHECK_ICMP 0x0800
#define NETIF_CHECKSUM_CHECK_ICMP6 0x1000
#define NETIF_CHECKSUM_ENABLE_ALL 0xFFFF
#define NETIF_CHECKSUM_DISABLE_ALL 0x0000
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
struct netif;
/** Function prototype for netif init functions. Set up flags and output/linkoutput
@ -240,6 +255,9 @@ struct netif {
/* the hostname for this netif, NULL is a valid value */
char* hostname;
#endif /* LWIP_NETIF_HOSTNAME */
#if LWIP_CHECKSUM_CTRL_PER_NETIF
u16_t chksum_flags;
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF*/
/** maximum transfer unit (in bytes) */
u16_t mtu;
/** number of bytes used in hwaddr */
@ -292,12 +310,21 @@ struct netif {
#endif /* ENABLE_LOOPBACK */
};
#if LWIP_CHECKSUM_CTRL_PER_NETIF
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags) do { \
(netif)->chksum_flags = chksumflags; } while(0)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag) if (((netif) == NULL) || (((netif)->chksum_flags & (chksumflag)) != 0))
#else /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#define NETIF_SET_CHECKSUM_CTRL(netif, chksumflags)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#endif /* LWIP_CHECKSUM_CTRL_PER_NETIF */
#if LWIP_SNMP
#define NETIF_INIT_SNMP(netif, type, speed) \
#define NETIF_INIT_SNMP(netif, type, speed) do { \
/* use "snmp_ifType" enum from snmp.h for "type", snmp_ifType_ethernet_csmacd by example */ \
(netif)->link_type = (type); \
(netif)->link_type = (type); \
/* your link speed here (units: bits per second) */ \
(netif)->link_speed = (speed); \
(netif)->link_speed = (speed);\
(netif)->ts = 0; \
(netif)->ifinoctets = 0; \
(netif)->ifinucastpkts = 0; \
@ -306,7 +333,7 @@ struct netif {
(netif)->ifoutoctets = 0; \
(netif)->ifoutucastpkts = 0; \
(netif)->ifoutnucastpkts = 0; \
(netif)->ifoutdiscards = 0
(netif)->ifoutdiscards = 0; } while(0)
#else /* LWIP_SNMP */
#define NETIF_INIT_SNMP(netif, type, speed)
#endif /* LWIP_SNMP */

View File

@ -2443,6 +2443,16 @@
---------- Checksum options ----------
--------------------------------------
*/
/**
* LWIP_CHECKSUM_CTRL_PER_NETIF==1: Checksum generation/check can be enabled/disabled
* per netif.
* ATTENTION: if enabled, the CHECKSUM_GEN_* and CHECKSUM_CHECK_* defines must be enabled!
*/
#ifndef LWIP_CHECKSUM_CTRL_PER_NETIF
#define LWIP_CHECKSUM_CTRL_PER_NETIF 0
#endif
/**
* CHECKSUM_GEN_IP==1: Generate checksums in software for outgoing IP packets.
*/