From owner-dev-commits-src-branches@freebsd.org Thu May 27 11:07:46 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id E246763A43A; Thu, 27 May 2021 11:07:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FrQ5Z62Xpz3C89; Thu, 27 May 2021 11:07:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id B323222DB8; Thu, 27 May 2021 11:07:46 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 14RB7khH013954; Thu, 27 May 2021 11:07:46 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14RB7k0K013953; Thu, 27 May 2021 11:07:46 GMT (envelope-from git) Date: Thu, 27 May 2021 11:07:46 GMT Message-Id: <202105271107.14RB7k0K013953@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Lutz Donnerhacke Subject: git: d9a06ae65043 - stable/12 - netgraph/ng_bridge: learn MACs via control message MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: donner X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: d9a06ae65043b6a21cb816ed10d26cb947876d67 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 May 2021 11:07:46 -0000 The branch stable/12 has been updated by donner: URL: https://cgit.FreeBSD.org/src/commit/?id=d9a06ae65043b6a21cb816ed10d26cb947876d67 commit d9a06ae65043b6a21cb816ed10d26cb947876d67 Author: Lutz Donnerhacke AuthorDate: 2021-05-04 20:14:59 +0000 Commit: Lutz Donnerhacke CommitDate: 2021-05-27 11:00:17 +0000 netgraph/ng_bridge: learn MACs via control message Add a new control message to move ethernet addresses to a given link in ng_bridge(4). Send this message instead of doing the work directly. This decouples the read-only activity from the modification under a more strict writer lock. Decoupling the work is a prerequisite for multithreaded operation. Approved by: manpages (bcr), kp (earlier version) Differential Revision: https://reviews.freebsd.org/D28516 (cherry picked from commit b1bd44732d8332930dc6a17092f47a201caff1ef) --- share/man/man4/ng_bridge.4 | 21 +++++++++++++- sys/netgraph/ng_bridge.c | 69 ++++++++++++++++++++++++++++++++++++++++------ sys/netgraph/ng_bridge.h | 11 ++++++++ 3 files changed, 91 insertions(+), 10 deletions(-) diff --git a/share/man/man4/ng_bridge.4 b/share/man/man4/ng_bridge.4 index 1451773711e9..e3f406c3f437 100644 --- a/share/man/man4/ng_bridge.4 +++ b/share/man/man4/ng_bridge.4 @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd February 6, 2021 +.Dd February 17, 2021 .Dt NG_BRIDGE 4 .Os .Sh NAME @@ -214,6 +214,25 @@ Returns the current host mapping table used to direct packets, in a .Dv "struct ng_bridge_host_ary" . .It Dv NGM_BRIDGE_SET_PERSISTENT Pq Ic setpersistent This command sets the persistent flag on the node, and takes no arguments. +.It Dv NGM_BRIDGE_MOVE_HOST Pq Ar movehost +This command takes a +.Vt "struct ng_bridge_move_host" +as an argument. +It assigns the MAC +.Va addr +to the +.Va hook , +which must not be assigned yet. +If the +.Va hook +is the empty string, the incoming hook of the control message is +used as fallback. +.Bd -literal -offset 0n +struct ng_bridge_move_host { + u_char addr[ETHER_ADDR_LEN]; /* ethernet address */ + char hook[NG_HOOKSIZ]; /* link where addr can be found */ +}; +.Ed .El .Sh SHUTDOWN This node shuts down upon receipt of a diff --git a/sys/netgraph/ng_bridge.c b/sys/netgraph/ng_bridge.c index 3243319c99e8..0d5e2ffb196d 100644 --- a/sys/netgraph/ng_bridge.c +++ b/sys/netgraph/ng_bridge.c @@ -234,6 +234,13 @@ static const struct ng_parse_type ng_bridge_stats_type = { &ng_parse_struct_type, &ng_bridge_stats_type_fields }; +/* Parse type for struct ng_bridge_move_host */ +static const struct ng_parse_struct_field ng_bridge_move_host_type_fields[] + = NG_BRIDGE_MOVE_HOST_TYPE_INFO(&ng_parse_enaddr_type); +static const struct ng_parse_type ng_bridge_move_host_type = { + &ng_parse_struct_type, + &ng_bridge_move_host_type_fields +}; /* List of commands and how to convert arguments to/from ASCII */ static const struct ng_cmdlist ng_bridge_cmdlist[] = { @@ -293,6 +300,13 @@ static const struct ng_cmdlist ng_bridge_cmdlist[] = { NULL, NULL }, + { + NGM_BRIDGE_COOKIE, + NGM_BRIDGE_MOVE_HOST, + "movehost", + &ng_bridge_move_host_type, + NULL + }, { 0 } }; @@ -669,6 +683,32 @@ ng_bridge_rcvmsg(node_p node, item_p item, hook_p lasthook) priv->persistent = 1; break; } + case NGM_BRIDGE_MOVE_HOST: + { + struct ng_bridge_move_host *mh; + hook_p hook; + struct ng_bridge_host *host; + + if (msg->header.arglen < sizeof(*mh)) { + error = EINVAL; + break; + } + mh = (struct ng_bridge_move_host *)msg->data; + hook = (mh->hook[0] == 0) + ? lasthook + : ng_findhook(node, mh->hook); + if (hook == NULL) { + error = ENOENT; + break; + } + host = ng_bridge_get(priv, mh->addr); + if (host != NULL) { + error = EADDRINUSE; + break; + } + error = ng_bridge_put(priv, mh->addr, NG_HOOK_PRIVATE(hook)); + break; + } default: error = EINVAL; break; @@ -885,12 +925,26 @@ ng_bridge_rcvdata(hook_p hook, item_p item) host->age = 0; } } else if (ctx.incoming->learnMac) { - if (!ng_bridge_put(priv, eh->ether_shost, ctx.incoming)) { + struct ng_mesg *msg; + struct ng_bridge_move_host *mh; + int error = 0; + + NG_MKMESSAGE(msg, NGM_BRIDGE_COOKIE, NGM_BRIDGE_MOVE_HOST, + sizeof(*mh), M_NOWAIT); + if (msg == NULL) { counter_u64_add(ctx.incoming->stats.memoryFailures, 1); NG_FREE_ITEM(item); NG_FREE_M(ctx.m); return (ENOMEM); } + mh = (struct ng_bridge_move_host *)msg->data; + strncpy(mh->hook, NG_HOOK_NAME(ctx.incoming->hook), + sizeof(mh->hook)); + memcpy(mh->addr, eh->ether_shost, sizeof(mh->addr)); + NG_SEND_MSG_ID(error, node, msg, NG_NODE_ID(node), + NG_NODE_ID(node)); + if (error) + counter_u64_add(ctx.incoming->stats.memoryFailures, 1); } /* Run packet through ipfw processing, if enabled */ @@ -1035,8 +1089,7 @@ ng_bridge_get(priv_cp priv, const u_char *addr) /* * Add a new host entry to the table. This assumes the host doesn't - * already exist in the table. Returns 1 on success, 0 if there - * was a memory allocation failure. + * already exist in the table. Returns 0 on success. */ static int ng_bridge_put(priv_p priv, const u_char *addr, link_p link) @@ -1046,16 +1099,14 @@ ng_bridge_put(priv_p priv, const u_char *addr, link_p link) #ifdef INVARIANTS /* Assert that entry does not already exist in hashtable */ - SLIST_FOREACH(host, &priv->tab[bucket], next) { - KASSERT(!ETHER_EQUAL(host->addr, addr), - ("%s: entry %6D exists in table", __func__, addr, ":")); - } + KASSERT(ng_bridge_get(priv, addr) == NULL, + ("%s: entry %6D exists in table", __func__, addr, ":")); #endif /* Allocate and initialize new hashtable entry */ host = malloc(sizeof(*host), M_NETGRAPH_BRIDGE, M_NOWAIT); if (host == NULL) - return (0); + return (ENOMEM); bcopy(addr, host->addr, ETHER_ADDR_LEN); host->link = link; host->staleness = 0; @@ -1067,7 +1118,7 @@ ng_bridge_put(priv_p priv, const u_char *addr, link_p link) /* Resize table if necessary */ ng_bridge_rehash(priv); - return (1); + return (0); } /* diff --git a/sys/netgraph/ng_bridge.h b/sys/netgraph/ng_bridge.h index 790e9c5da11e..7d9c1a22bb6e 100644 --- a/sys/netgraph/ng_bridge.h +++ b/sys/netgraph/ng_bridge.h @@ -183,6 +183,16 @@ struct ng_bridge_host_tbl_ary { }; #endif /* NGM_BRIDGE_TABLE_ABI */ +struct ng_bridge_move_host { + u_char addr[ETHER_ADDR_LEN]; /* ethernet address */ + char hook[NG_HOOKSIZ]; /* link where addr can be found */ +}; +/* Keep this in sync with the above structure definition */ +#define NG_BRIDGE_MOVE_HOST_TYPE_INFO(entype) { \ + { "addr", (entype) }, \ + { "hook", &ng_parse_hookbuf_type }, \ +} + /* Netgraph control messages */ enum { NGM_BRIDGE_SET_CONFIG = 1, /* set node configuration */ @@ -193,6 +203,7 @@ enum { NGM_BRIDGE_GETCLR_STATS, /* atomically get & clear link stats */ NGM_BRIDGE_GET_TABLE, /* get link table */ NGM_BRIDGE_SET_PERSISTENT, /* set persistent mode */ + NGM_BRIDGE_MOVE_HOST, /* move a host to a link */ }; #endif /* _NETGRAPH_NG_BRIDGE_H_ */