The branch main has been updated by donner:

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

commit b1bd44732d8332930dc6a17092f47a201caff1ef
Author:     Lutz Donnerhacke <don...@freebsd.org>
AuthorDate: 2021-05-04 20:14:59 +0000
Commit:     Lutz Donnerhacke <don...@freebsd.org>
CommitDate: 2021-05-04 20:14:59 +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)
    MFC:            3 weeks
    Differential Revision:  https://reviews.freebsd.org/D28516
---
 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 be128d62c938..216dea3c392a 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
 .Vt "struct ng_bridge_host_ary" .
 .It Dv NGM_BRIDGE_SET_PERSISTENT Pq Ar 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 7b03b1a2599b..915a18550cba 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 }
 };
 
@@ -601,6 +615,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;
@@ -809,12 +849,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 */
@@ -959,8 +1013,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)
@@ -970,16 +1023,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;
@@ -991,7 +1042,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 03541deceacd..12717d16ac7a 100644
--- a/sys/netgraph/ng_bridge.h
+++ b/sys/netgraph/ng_bridge.h
@@ -140,6 +140,16 @@ struct ng_bridge_host_ary {
          { NULL }                                              \
 }
 
+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 */
@@ -150,6 +160,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_ */
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to