diff options
author | bms <bms@FreeBSD.org> | 2006-09-25 10:11:16 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2006-09-25 10:11:16 +0000 |
commit | 27d7e8be08d5080b783ef437149fc4f7fc3adfde (patch) | |
tree | 32da2515bec6367ff396b9b72c433ec025da3189 /sys | |
parent | 7766e0a26b4a6088ea3cd0c32d8450ce1e25535b (diff) | |
download | FreeBSD-src-27d7e8be08d5080b783ef437149fc4f7fc3adfde.zip FreeBSD-src-27d7e8be08d5080b783ef437149fc4f7fc3adfde.tar.gz |
Account for output IP datagrams on the ifaddr where they originated from,
*not* the first ifaddr on the ifp. This is similar to what NetBSD does.
PR: kern/72936
Submitted by: alfred
Reviewed by: andre
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in_var.h | 17 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 17 |
2 files changed, 26 insertions, 8 deletions
diff --git a/sys/netinet/in_var.h b/sys/netinet/in_var.h index 319b0dc..9669a1b 100644 --- a/sys/netinet/in_var.h +++ b/sys/netinet/in_var.h @@ -94,6 +94,19 @@ extern u_long in_ifaddrhmask; /* mask for hash table */ #define INADDR_HASH(x) \ (&in_ifaddrhashtbl[INADDR_HASHVAL(x) & in_ifaddrhmask]) +/* + * Macro for finding the internet address structure (in_ifaddr) corresponding + * corresponding to one of our IP addresses (in_addr). + */ +#define INADDR_TO_IFADDR(addr, ia) \ + /* struct in_addr addr; */ \ + /* struct in_ifaddr *ia; */ \ +do { \ +\ + LIST_FOREACH(ia, INADDR_HASH((addr).s_addr), ia_hash) \ + if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \ + break; \ +} while (0) /* * Macro for finding the interface (ifnet structure) corresponding to one @@ -105,9 +118,7 @@ extern u_long in_ifaddrhmask; /* mask for hash table */ { \ struct in_ifaddr *ia; \ \ - LIST_FOREACH(ia, INADDR_HASH((addr).s_addr), ia_hash) \ - if (IA_SIN(ia)->sin_addr.s_addr == (addr).s_addr) \ - break; \ + INADDR_TO_IFADDR(addr, ia); \ (ifp) = (ia == NULL) ? NULL : ia->ia_ifp; \ } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2675385..33fa325 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -116,6 +116,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int len, error = 0; struct sockaddr_in *dst = NULL; /* keep compiler happy */ struct in_ifaddr *ia = NULL; + struct in_ifaddr *sia = NULL; int isbroadcast, sw_csum; struct route iproute; struct in_addr odst; @@ -532,12 +533,15 @@ passout: * once instead of for every generated packet. */ if (!(flags & IP_FORWARDING) && ia) { + INADDR_TO_IFADDR(ip->ip_src, sia); + if (sia == NULL) + sia = ia; if (m->m_pkthdr.csum_flags & CSUM_TSO) - ia->ia_ifa.if_opackets += + sia->ia_ifa.if_opackets += m->m_pkthdr.len / m->m_pkthdr.tso_segsz; else - ia->ia_ifa.if_opackets++; - ia->ia_ifa.if_obytes += m->m_pkthdr.len; + sia->ia_ifa.if_opackets++; + sia->ia_ifa.if_obytes += m->m_pkthdr.len; } #ifdef IPSEC /* clean ipsec history once it goes out of the node */ @@ -582,8 +586,11 @@ passout: if (error == 0) { /* Record statistics for this interface address. */ if (ia != NULL) { - ia->ia_ifa.if_opackets++; - ia->ia_ifa.if_obytes += m->m_pkthdr.len; + INADDR_TO_IFADDR(ip->ip_src, sia); + if (sia == NULL) + sia = ia; + sia->ia_ifa.if_opackets++; + sia->ia_ifa.if_obytes += m->m_pkthdr.len; } /* * Reset layer specific mbuf flags |