Hi, Cleanup the error handling in ipsec ipip_output() and consistently goto drop instead of return. This will help to refactor counter and add tdb refcounting. An ENOBUFS should be EINVAL in IPv6 case. Also use combined packet and byte counter.
ok? bluhm Index: netinet/ip_ipip.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipip.c,v retrieving revision 1.93 diff -u -p -r1.93 ip_ipip.c --- netinet/ip_ipip.c 8 Jul 2021 21:07:19 -0000 1.93 +++ netinet/ip_ipip.c 4 Oct 2021 22:46:27 -0000 @@ -343,6 +343,7 @@ ipip_output(struct mbuf *m, struct tdb * #ifdef ENCDEBUG char buf[INET6_ADDRSTRLEN]; #endif + int error; /* XXX Deal with empty TDB source/destination addresses. */ @@ -361,17 +362,16 @@ ipip_output(struct mbuf *m, struct tdb * ntohl(tdb->tdb_spi)); ipipstat_inc(ipips_unspec); - m_freem(m); - *mp = NULL; - return EINVAL; + error = EINVAL; + goto drop; } M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); if (m == NULL) { DPRINTF("M_PREPEND failed"); ipipstat_inc(ipips_hdrops); - *mp = NULL; - return ENOBUFS; + error = ENOBUFS; + goto drop; } ipo = mtod(m, struct ip *); @@ -424,15 +424,18 @@ ipip_output(struct mbuf *m, struct tdb * } #endif /* INET6 */ else { - m_freem(m); - *mp = NULL; ipipstat_inc(ipips_family); - return EAFNOSUPPORT; + error = EAFNOSUPPORT; + goto drop; } otos = 0; ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); ipo->ip_tos = otos; + + obytes = m->m_pkthdr.len - sizeof(struct ip); + if (tdb->tdb_xform->xf_type == XF_IP4) + tdb->tdb_cur_bytes += obytes; break; #ifdef INET6 @@ -447,9 +450,8 @@ ipip_output(struct mbuf *m, struct tdb * ntohl(tdb->tdb_spi)); ipipstat_inc(ipips_unspec); - m_freem(m); - *mp = NULL; - return ENOBUFS; + error = EINVAL; + goto drop; } /* If the inner protocol is IPv6, clear link local scope */ @@ -466,8 +468,8 @@ ipip_output(struct mbuf *m, struct tdb * if (m == NULL) { DPRINTF("M_PREPEND failed"); ipipstat_inc(ipips_hdrops); - *mp = NULL; - return ENOBUFS; + error = ENOBUFS; + goto drop; } /* Initialize IPv6 header */ @@ -501,49 +503,37 @@ ipip_output(struct mbuf *m, struct tdb * ip6o->ip6_nxt = IPPROTO_IPV6; } else { - m_freem(m); - *mp = NULL; ipipstat_inc(ipips_family); - return EAFNOSUPPORT; + error = EAFNOSUPPORT; + goto drop; } otos = 0; ip_ecn_ingress(ECN_ALLOWED, &otos, &itos); ip6o->ip6_flow |= htonl((u_int32_t) otos << 20); + + obytes = m->m_pkthdr.len - sizeof(struct ip6_hdr); + if (tdb->tdb_xform->xf_type == XF_IP4) + tdb->tdb_cur_bytes += obytes; break; #endif /* INET6 */ default: DPRINTF("unsupported protocol family %d", tdb->tdb_dst.sa.sa_family); - m_freem(m); - *mp = NULL; ipipstat_inc(ipips_family); - return EAFNOSUPPORT; + error = EAFNOSUPPORT; + goto drop; } - ipipstat_inc(ipips_opackets); *mp = m; - - if (tdb->tdb_dst.sa.sa_family == AF_INET) { - obytes = m->m_pkthdr.len - sizeof(struct ip); - if (tdb->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += obytes; - - ipipstat_add(ipips_obytes, obytes); - } - -#ifdef INET6 - if (tdb->tdb_dst.sa.sa_family == AF_INET6) { - obytes = m->m_pkthdr.len - sizeof(struct ip6_hdr); - if (tdb->tdb_xform->xf_type == XF_IP4) - tdb->tdb_cur_bytes += obytes; - - ipipstat_add(ipips_obytes, obytes); - } -#endif /* INET6 */ - + ipipstat_pkt(ipips_opackets, ipips_obytes, obytes); return 0; + + drop: + m_freem(m); + *mp = NULL; + return error; } #ifdef IPSEC Index: netinet/ip_ipip.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipip.h,v retrieving revision 1.11 diff -u -p -r1.11 ip_ipip.h --- netinet/ip_ipip.h 4 Oct 2019 05:00:49 -0000 1.11 +++ netinet/ip_ipip.h 4 Oct 2021 22:43:46 -0000 @@ -104,6 +104,12 @@ ipipstat_add(enum ipipstat_counters c, u counters_add(ipipcounters, c, v); } +static inline void +ipipstat_pkt(enum ipipstat_counters p, enum ipipstat_counters b, uint64_t v) +{ + counters_pkt(ipipcounters, p, b, v); +} + struct tdb; void ipip_init(void); Index: netinet/ip_ipsp.h =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ip_ipsp.h,v retrieving revision 1.207 diff -u -p -r1.207 ip_ipsp.h --- netinet/ip_ipsp.h 29 Sep 2021 22:08:13 -0000 1.207 +++ netinet/ip_ipsp.h 4 Oct 2021 23:07:53 -0000 @@ -191,6 +191,12 @@ ipsecstat_add(enum ipsec_counters c, uin counters_add(ipseccounters, c, v); } +static inline void +ipsecstat_pkt(enum ipsec_counters p, enum ipsec_counters b, uint64_t v) +{ + counters_pkt(ipseccounters, p, b, v); +} + struct m_tag; #define sen_data Sen.Data Index: netinet/ipsec_input.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_input.c,v retrieving revision 1.180 diff -u -p -r1.180 ipsec_input.c --- netinet/ipsec_input.c 29 Sep 2021 22:08:13 -0000 1.180 +++ netinet/ipsec_input.c 4 Oct 2021 23:12:24 -0000 @@ -200,8 +200,7 @@ ipsec_common_input(struct mbuf *m, int s NET_ASSERT_LOCKED(); - ipsecstat_inc(ipsec_ipackets); - ipsecstat_add(ipsec_ibytes, m->m_pkthdr.len); + ipsecstat_pkt(ipsec_ipackets, ipsec_ibytes, m->m_pkthdr.len); IPSEC_ISTAT(esps_input, ahs_input, ipcomps_input); if (m == NULL) { Index: netinet/ipsec_output.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/ipsec_output.c,v retrieving revision 1.86 diff -u -p -r1.86 ipsec_output.c --- netinet/ipsec_output.c 27 Jul 2021 17:13:03 -0000 1.86 +++ netinet/ipsec_output.c 4 Oct 2021 22:49:37 -0000 @@ -583,8 +583,7 @@ ipsp_process_done(struct mbuf *m, struct m_tag_prepend(m, mtag); - ipsecstat_inc(ipsec_opackets); - ipsecstat_add(ipsec_obytes, m->m_pkthdr.len); + ipsecstat_pkt(ipsec_opackets, ipsec_obytes, m->m_pkthdr.len); tdb->tdb_opackets++; tdb->tdb_obytes += m->m_pkthdr.len;