git: 601438fbfa8e - main - carp: refactor packet tagging for ether_output()

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 08 May 2024 11:19:57 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=601438fbfa8e5aa47b6e3417b253c10cd9b34d1d

commit 601438fbfa8e5aa47b6e3417b253c10cd9b34d1d
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2024-04-30 02:36:42 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-05-08 11:19:04 +0000

    carp: refactor packet tagging for ether_output()
    
    - Separate HMAC preparation (CARP specific) from tagging.
    - In unicast mode (CARP specific) don't put tag at all.
    - Don't put pointer to software context into the tag.  Putting just vhid,
      an integer value, is a safer design.
    
    Reviewed by:    kp
    Differential Revision:  https://reviews.freebsd.org/D45038
---
 sys/netinet/ip_carp.c | 37 ++++++++++++++-----------------------
 1 file changed, 14 insertions(+), 23 deletions(-)

diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index de439df97c59..d7dd6ced2e44 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1055,22 +1055,24 @@ carp_tag(struct carp_softc *sc, struct mbuf *m)
 	struct m_tag *mtag;
 
 	/* Tag packet for carp_output */
-	if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(struct carp_softc *),
+	if ((mtag = m_tag_get(PACKET_TAG_CARP, sizeof(sc->sc_vhid),
 	    M_NOWAIT)) == NULL) {
 		m_freem(m);
 		CARPSTATS_INC(carps_onomem);
 		return (ENOMEM);
 	}
-	bcopy(&sc, mtag + 1, sizeof(sc));
+	bcopy(&sc->sc_vhid, mtag + 1, sizeof(sc->sc_vhid));
 	m_tag_prepend(m, mtag);
 
 	return (0);
 }
 
-static int
+static void
 carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
 {
 
+	MPASS(sc->sc_version == CARP_VERSION_CARP);
+
 	if (sc->sc_init_counter) {
 		/* this could also be seconds since unix epoch */
 		sc->sc_counter = arc4random();
@@ -1083,8 +1085,6 @@ carp_prepare_ad(struct mbuf *m, struct carp_softc *sc, struct carp_header *ch)
 	ch->carp_counter[1] = htonl(sc->sc_counter&0xffffffff);
 
 	carp_hmac_generate(sc, ch->carp_counter, ch->carp_md);
-
-	return (carp_tag(sc, m));
 }
 
 static inline void
@@ -1273,7 +1273,9 @@ carp_send_ad_locked(struct carp_softc *sc)
 
 		ch_ptr = (struct carp_header *)(&ip[1]);
 		bcopy(&ch, ch_ptr, sizeof(ch));
-		if (carp_prepare_ad(m, sc, ch_ptr))
+		carp_prepare_ad(m, sc, ch_ptr);
+		if (IN_MULTICAST(ntohl(sc->sc_carpaddr.s_addr)) &&
+		    carp_tag(sc, m) != 0)
 			goto resched;
 
 		m->m_data += sizeof(*ip);
@@ -1333,7 +1335,9 @@ carp_send_ad_locked(struct carp_softc *sc)
 
 		ch_ptr = (struct carp_header *)(&ip6[1]);
 		bcopy(&ch, ch_ptr, sizeof(ch));
-		if (carp_prepare_ad(m, sc, ch_ptr))
+		carp_prepare_ad(m, sc, ch_ptr);
+		if (IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6) &&
+		    carp_tag(sc, m) != 0)
 			goto resched;
 
 		m->m_data += sizeof(*ip6);
@@ -2019,7 +2023,7 @@ int
 carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
 {
 	struct m_tag *mtag;
-	struct carp_softc *sc;
+	int vhid;
 
 	if (!sa)
 		return (0);
@@ -2041,20 +2045,7 @@ carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
 	if (mtag == NULL)
 		return (0);
 
-	bcopy(mtag + 1, &sc, sizeof(sc));
-
-	switch (sa->sa_family) {
-	case AF_INET:
-		if (! IN_MULTICAST(ntohl(sc->sc_carpaddr.s_addr)))
-			return (0);
-		break;
-	case AF_INET6:
-		if (! IN6_IS_ADDR_MULTICAST(&sc->sc_carpaddr6))
-			return (0);
-		break;
-	default:
-		panic("Unknown af");
-	}
+	bcopy(mtag + 1, &vhid, sizeof(vhid));
 
 	/* Set the source MAC address to the Virtual Router MAC Address. */
 	switch (ifp->if_type) {
@@ -2069,7 +2060,7 @@ carp_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *sa)
 			eh->ether_shost[2] = 0x5e;
 			eh->ether_shost[3] = 0;
 			eh->ether_shost[4] = 1;
-			eh->ether_shost[5] = sc->sc_vhid;
+			eh->ether_shost[5] = vhid;
 		}
 		break;
 	default: