FreeBSD Bugzilla – Attachment 207625 Details for
Bug 240685
netgraph/ng_vlan_rotate: IEEE 802.1ad VLAN manipulation netgraph node type (new type)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for netgraph/ng_vlan_rotate module
file_240685.txt (text/plain), 29.01 KB, created by
Lutz Donnerhacke
on 2019-09-19 13:00:25 UTC
(
hide
)
Description:
Patch for netgraph/ng_vlan_rotate module
Filename:
MIME Type:
Creator:
Lutz Donnerhacke
Created:
2019-09-19 13:00:25 UTC
Size:
29.01 KB
patch
obsolete
>Index: share/man/man4/Makefile >=================================================================== >--- share/man/man4/Makefile (revision 351934) >+++ share/man/man4/Makefile (working copy) >@@ -381,6 +381,7 @@ > ng_uni.4 \ > ng_vjc.4 \ > ng_vlan.4 \ >+ ng_vlan_rotate.4 \ > nmdm.4 \ > nsp.4 \ > ${_ntb.4} \ >Index: share/man/man4/ng_vlan_rotate.4 >=================================================================== >--- share/man/man4/ng_vlan_rotate.4 (nonexistent) >+++ share/man/man4/ng_vlan_rotate.4 (working copy) >@@ -0,0 +1,253 @@ >+.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD >+.\" >+.\" Copyright (c) 2019 IKS Service GmbH >+.\" All rights reserved. >+.\" >+.\" Redistribution and use in source and binary forms, with or without >+.\" modification, are permitted provided that the following conditions >+.\" are met: >+.\" 1. Redistributions of source code must retain the above copyright >+.\" notice, this list of conditions and the following disclaimer. >+.\" 2. Redistributions in binary form must reproduce the above copyright >+.\" notice, this list of conditions and the following disclaimer in the >+.\" documentation and/or other materials provided with the distribution. >+.\" >+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND >+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE >+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+.\" SUCH DAMAGE. >+.\" >+.\" Author: Lutz Donnerhacke <lutz@donnerhacke.de> >+.\" >+.\" $FreeBSD$ >+.\" >+.Dd September 19, 2019 >+.Dt NG_VLAN_ROTATE 4 >+.Os >+.Sh NAME >+.Nm ng_vlan_rotate >+.Nd IEEE 802.1ad VLAN manipulation netgraph node type >+.Sh SYNOPSIS >+.In sys/types.h >+.In netgraph.h >+.In netgraph/ng_vlan_rotate.h >+.Sh DESCRIPTION >+The >+.Nm vlan_rotate >+node type manipulates the order of VLAN tags of frames tagged according to >+the IEEE 802.1ad (an extension of IEEE 802.1Q) standard between different hooks. >+.Pp >+Each node has four special hooks, >+.Va original , >+.Va ordered , >+.Va excessive , >+and >+.Va incomplete . >+.Pp >+A frame tagged with an arbitrary number of >+.Dv ETHERTYPE_VLAN , >+.Dv ETHERTYPE_QINQ , >+and >+.Dv 0x9100 >+tags received on the >+.Va original >+hook will be rearranged to a new order of those tags and >+is sent out the >+.Dq ordered >+hook. >+After successful processing the >+.Va histogram >+counter for the observed stack size increments. >+.Pp >+If it contains fewer VLANs in the stack, than the configured >+.Va min >+limit, the frame is send out to the >+.Va incomplete >+hook and the >+.Va incomplete >+counter increments. >+.Pp >+If it contains more VLANs in the stack, than the configured >+.Va max >+limit, the frame is send out to the >+.Va excessive >+hook and the >+.Va excessive >+counter increments. >+.Pp >+If any destination hook is not connected, the frame is dropped and the >+.Va drops >+counter increments. >+.Pp >+For Ethernet frames received on the >+.Va ordered >+hook, the transformation is reversed and is passed to the >+.Va original >+hook. Please note, that this process is identical to the one described >+above, besides the ordered/original hooks and the transformation are >+swapped. >+.Pp >+An Ethernet frame received on >+.Va incomplede >+or >+.Va excessive >+hook is forwarded to the >+.Va original >+hook without any modification. >+.Pp >+This node supports only one operation at the moment: Rotation of the >+VLANs in the stack. Setting the configuration parameter >+.Va rot >+to a positive value, the stack will roll up by this amount. Negative >+values will roll down. A typical scenario is setting the value to 1 >+in order to bring the innermost VLAN tag to the outmost level. >+Rotation includes the VLAN id and the ethertype, but the QOS >+paramenters pcp and cfi stay in place. Typical QOS handling refers to >+the outmost setting, so this scheme keeps QOS intact. >+.Sh HOOKS >+This node type supports the following hooks: >+.Bl -tag -width incomplete >+.It Va original >+Typically this hook would be connected to a >+.Xr ng_ether 4 >+node, using the >+.Va lower >+hook connected to a carrier network. >+.It Va ordered >+Typically this hook would be connected to a >+.Xr ng_vlan 4 >+type node using the >+.Va downstream >+hook in order to seperate services. >+.It Va excessive >+see below. >+.It Va incomplete >+Typically those hooks would be attached to an >+.Xr ng_eiface 4 >+type node using the >+.Va ether >+hook for anomaly monitoring purposes. >+.El >+.Sh CONTROL MESSAGES >+This node type supports the generic control messages, plus the following: >+.Bl -tag -width foo >+.It Dv NGM_VLANROTATE_GET_CONF Pq Ic getconf >+Read the current configuration. >+.It Dv NGM_VLANROTATE_SET_CONF Pq Ic setconf >+Set the current configuration. >+.It Dv NGM_VLANROTATE_GET_STAT Pq Ic getstat >+Read the current statistics. >+.It Dv NGM_VLANROTATE_CLR_STAT Pq Ic clrstat >+Zeroize the statistics. >+.It Dv NGM_VLANROTATE_GETCLR_STAT Pq Ic getclrstat >+Read the current statistics and zeroize it in one step. >+.El >+.Sh EXAMPLES >+The first example demonstrates how to rotate double or triple tagged >+frames so, that the innermost C-VLAN can be used as service >+discriminator. The single or double tagged frames (C-VLAN >+removed) are send out the an interface pointing to different >+infrastucture. >+.Bd -literal >+#!/bin/sh >+ >+BNG_IF=ixl3 >+VOIP_IF=bge2 >+ >+ngctl -f- <<EOF >+mkpeer ${BNG_IF}: vlan_rotate lower original >+name ${BNG_IF}:lower rotate >+msg rotate: setconf { min=2 max=3 rot=1 } >+mkpeer rotate: vlan ordered downstream >+name rotate:ordered services >+connect services: ${VOIP_IF} voip lower >+msg services: addfilter { vlan=123 hook="voip" } >+EOF >+.Ed >+ >+Let's inject the following sample frame on the >+.Dv BNG_IF >+interface: >+.Bd -literal >+00:00:00:00:01:01 > 00:01:02:03:04:05, >+ ethertype 802.1Q-9100 (0x9100), length 110: vlan 2, p 1, >+ ethertype 802.1Q-QinQ, vlan 101, p 0, >+ ethertype 802.1Q, vlan 123, p 7, >+ ethertype IPv4, (tos 0x0, ttl 64, id 15994, offset 0, flags [none], >+ proto ICMP (1), length 84) 192.168.140.101 > 192.168.140.1: >+ ICMP echo request, id 40234, seq 0, length 64 >+.Ed >+ >+The frame ejected on the >+.Va ordered >+hook will look like this: >+.Bd -literal >+00:00:00:00:01:01 > 00:01:02:03:04:05, >+ ethertype 802.1Q (0x8100), length 110: vlan 123, p 1, >+ ethertype 802.1Q-9100, vlan 2, p 0, >+ ethertype 802.1Q-QinQ, vlan 101, p 7, >+ ethertype IPv4, (tos 0x0, ttl 64, id 15994, offset 0, flags [none], >+ proto ICMP (1), length 84) 192.168.140.101 > 192.168.140.1: >+ ICMP echo request, id 40234, seq 0, length 64 >+.Ed >+ >+Hence the frame pushed out to the >+.Dv VOIP_IF >+will have this form: >+.Bd -literal >+00:00:00:00:01:01 > 00:01:02:03:04:05, >+ ethertype 802.1Q-9100, vlan 2, p 0, >+ ethertype 802.1Q-QinQ, vlan 101, p 7, >+ ethertype IPv4, (tos 0x0, ttl 64, id 15994, offset 0, flags [none], >+ proto ICMP (1), length 84) 192.168.140.101 > 192.168.140.1: >+ ICMP echo request, id 40234, seq 0, length 64 >+.Ed >+ >+.Pp >+The second example distinguish between double tagged and single tagged >+frames. Frames with more VLAN tags are dropped. >+.Bd -literal >+#!/bin/sh >+ >+IN_IF=bge1 >+ >+ngctl -f- <<EOF >+mkpeer ${IN_IF}: vlan_rotate lower original >+name ${IN_IF}:lower separate >+msg separate: setconf { min=1 max=1 rot=0 } >+mkpeer separate: eiface incomplete ether >+name separate:incomplete untagged >+mkpeer separate: eiface ordered ether >+name separate:ordered tagged >+EOF >+.Ed >+ >+Setting the >+.Va rot >+parameter to zero (or omitting it) does not change >+the order of the tags within the frame. >+ >+.Sh SHUTDOWN >+This node shuts down upon receipt of a >+.Dv NGM_SHUTDOWN >+control message, or when all hooks have been disconnected. >+.Sh SEE ALSO >+.Xr netgraph 4 , >+.Xr ng_eiface 4 , >+.Xr ng_ether 4 , >+.Xr ng_vlan 4 , >+.Xr ngctl 8 >+.Sh HISTORY >+The >+.Nm >+node type appeared in >+.Fx 12.1-PRERELEASE . >+.Sh AUTHORS >+.An Lutz Donnerhacke Aq Mt lutz@donnerhacke.de > >Index: sys/conf/files >=================================================================== >--- sys/conf/files (revision 351934) >+++ sys/conf/files (working copy) >@@ -4299,6 +4299,7 @@ > netgraph/ng_tty.c optional netgraph_tty > netgraph/ng_vjc.c optional netgraph_vjc > netgraph/ng_vlan.c optional netgraph_vlan >+netgraph/ng_vlan_rotate.c optional netgraph_vlan_rotate > netinet/accf_data.c optional accept_filter_data inet > netinet/accf_dns.c optional accept_filter_dns inet > netinet/accf_http.c optional accept_filter_http inet >Index: sys/modules/netgraph/Makefile >=================================================================== >--- sys/modules/netgraph/Makefile (revision 351934) >+++ sys/modules/netgraph/Makefile (working copy) >@@ -52,7 +52,8 @@ > tty \ > UI \ > vjc \ >- vlan >+ vlan \ >+ vlan_rotate > > .if ${MK_BLUETOOTH} != "no" || defined(ALL_MODULES) > _bluetooth= bluetooth >Index: sys/netgraph/ng_vlan_rotate.c >=================================================================== >--- sys/netgraph/ng_vlan_rotate.c (nonexistent) >+++ sys/netgraph/ng_vlan_rotate.c (working copy) >@@ -0,0 +1,483 @@ >+/* >+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD >+ * >+ * Copyright (c) 2019 IKS Service GmbH >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ * >+ * Author: Lutz Donnerhacke <lutz@donnerhacke.de> >+ * >+ * $FreeBSD$ >+ */ >+ >+#include <sys/param.h> >+#include <sys/systm.h> >+#include <sys/kernel.h> >+#include <sys/mbuf.h> >+#include <sys/malloc.h> >+#include <sys/ctype.h> >+#include <sys/errno.h> >+#include <sys/syslog.h> >+ >+#include <net/ethernet.h> >+ >+#include <netgraph/ng_message.h> >+#include <netgraph/ng_parse.h> >+#include <netgraph/ng_vlan_rotate.h> >+#include <netgraph/netgraph.h> >+ >+/* >+ * This section contains the netgraph method declarations for the >+ * sample node. These methods define the netgraph 'type'. >+ */ >+ >+static ng_constructor_t ng_vlanrotate_constructor; >+static ng_rcvmsg_t ng_vlanrotate_rcvmsg; >+static ng_shutdown_t ng_vlanrotate_shutdown; >+static ng_newhook_t ng_vlanrotate_newhook; >+static ng_rcvdata_t ng_vlanrotate_rcvdata; >+static ng_disconnect_t ng_vlanrotate_disconnect; >+ >+/* Parse type for struct ng_vlanrotate_conf. */ >+static const struct ng_parse_struct_field ng_vlanrotate_conf_fields[] = { >+ { "rot", &ng_parse_int8_type }, >+ { "min", &ng_parse_uint8_type }, >+ { "max", &ng_parse_uint8_type }, >+ { NULL } >+}; >+static const struct ng_parse_type ng_vlanrotate_conf_type = { >+ &ng_parse_struct_type, >+ &ng_vlanrotate_conf_fields >+}; >+ >+/* Parse type for struct ng_vlanrotate_stat. */ >+static struct ng_parse_fixedarray_info ng_vlanrotate_stat_hist_info = { >+ &ng_parse_uint64_type, >+ NG_VLANROTATE_MAX_VLANS >+}; >+static struct ng_parse_type ng_vlanrotate_stat_hist = { >+ &ng_parse_fixedarray_type, >+ &ng_vlanrotate_stat_hist_info >+}; >+static const struct ng_parse_struct_field ng_vlanrotate_stat_fields[] = { >+ { "drops", &ng_parse_uint64_type }, >+ { "excessive", &ng_parse_uint64_type }, >+ { "incomplete", &ng_parse_uint64_type }, >+ { "histogram", &ng_vlanrotate_stat_hist }, >+ { NULL } >+}; >+static struct ng_parse_type ng_vlanrotate_stat_type = { >+ &ng_parse_struct_type, >+ &ng_vlanrotate_stat_fields >+}; >+ >+ >+/* List of commands and how to convert arguments to/from ASCII */ >+static const struct ng_cmdlist ng_vlanrotate_cmdlist[] = { >+ { >+ NGM_VLANROTATE_COOKIE, >+ NGM_VLANROTATE_GET_CONF, >+ "getconf", >+ NULL, >+ &ng_vlanrotate_conf_type, >+ }, >+ { >+ NGM_VLANROTATE_COOKIE, >+ NGM_VLANROTATE_SET_CONF, >+ "setconf", >+ &ng_vlanrotate_conf_type, >+ NULL >+ }, >+ { >+ NGM_VLANROTATE_COOKIE, >+ NGM_VLANROTATE_GET_STAT, >+ "getstat", >+ NULL, >+ &ng_vlanrotate_stat_type >+ }, >+ { >+ NGM_VLANROTATE_COOKIE, >+ NGM_VLANROTATE_CLR_STAT, >+ "clrstat", >+ NULL, >+ &ng_vlanrotate_stat_type >+ }, >+ { >+ NGM_VLANROTATE_COOKIE, >+ NGM_VLANROTATE_GETCLR_STAT, >+ "getclrstat", >+ NULL, >+ &ng_vlanrotate_stat_type >+ }, >+ { 0 } >+}; >+ >+/* Netgraph node type descriptor */ >+static struct ng_type typestruct = { >+ .version = NG_ABI_VERSION, >+ .name = NG_VLANROTATE_NODE_TYPE, >+ .constructor = ng_vlanrotate_constructor, >+ .rcvmsg = ng_vlanrotate_rcvmsg, >+ .shutdown = ng_vlanrotate_shutdown, >+ .newhook = ng_vlanrotate_newhook, >+ .rcvdata = ng_vlanrotate_rcvdata, >+ .disconnect = ng_vlanrotate_disconnect, >+ .cmdlist = ng_vlanrotate_cmdlist, >+}; >+NETGRAPH_INIT(vlanrotate, &typestruct); >+ >+/* Information we store for each node */ >+struct vlanrotate { >+ hook_p original_hook; >+ hook_p ordered_hook; >+ hook_p excessive_hook; >+ hook_p incomplete_hook; >+ struct ng_vlanrotate_conf conf; >+ struct ng_vlanrotate_stat stat; >+}; >+typedef struct vlanrotate *vlanrotate_p; >+ >+/* >+ * Set up the private data structure. >+ */ >+static int >+ng_vlanrotate_constructor(node_p node) >+{ >+ vlanrotate_p vrp = malloc(sizeof(*vrp), M_NETGRAPH, M_WAITOK | M_ZERO); >+ >+ vrp->conf.max = NG_VLANROTATE_MAX_VLANS; >+ >+ NG_NODE_SET_PRIVATE(node, vrp); >+ return (0); >+} >+ >+/* >+ * Give our ok for a hook to be added. >+ */ >+static int >+ng_vlanrotate_newhook(node_p node, hook_p hook, const char *name) >+{ >+ const vlanrotate_p vrp = NG_NODE_PRIVATE(node); >+ hook_p *dst = NULL; >+ >+ if (strcmp(name, NG_VLANROTATE_HOOK_ORDERED) == 0) { >+ dst = &vrp->ordered_hook; >+ } else if (strcmp(name, NG_VLANROTATE_HOOK_ORIGINAL) == 0) { >+ dst = &vrp->original_hook; >+ } else if (strcmp(name, NG_VLANROTATE_HOOK_EXCESSIVE) == 0) { >+ dst = &vrp->excessive_hook; >+ } else if (strcmp(name, NG_VLANROTATE_HOOK_INCOMPLETE) == 0) { >+ dst = &vrp->incomplete_hook; >+ } >+ >+ if(dst == NULL) >+ return (EINVAL); /* not a hook we know about */ >+ >+ if(*dst != NULL) >+ return (EADDRINUSE); /* don't override */ >+ >+ *dst = hook; >+ return (0); >+} >+ >+/* >+ * Get a netgraph control message. >+ * We actually receive a queue item that has a pointer to the message. >+ * If we free the item, the message will be freed too, unless we remove >+ * it from the item using NGI_GET_MSG(); >+ * The return address is also stored in the item, as an ng_ID_t, >+ * accessible as NGI_RETADDR(item); >+ * Check it is one we understand. If needed, send a response. >+ * We could save the address for an async action later, but don't here. >+ * Always free the message. >+ * The response should be in a malloc'd region that the caller can 'free'. >+ * A response is not required. >+ */ >+static int >+ng_vlanrotate_rcvmsg(node_p node, item_p item, hook_p lasthook) >+{ >+ const vlanrotate_p vrp = NG_NODE_PRIVATE(node); >+ struct ng_mesg *resp = NULL; >+ int error = 0; >+ struct ng_mesg *msg; >+ struct ng_vlanrotate_conf * pcf; >+ >+ NGI_GET_MSG(item, msg); >+ /* Deal with message according to cookie and command */ >+ switch (msg->header.typecookie) { >+ case NGM_VLANROTATE_COOKIE: >+ switch (msg->header.cmd) { >+ case NGM_VLANROTATE_GET_CONF: >+ NG_MKRESPONSE(resp, msg, sizeof(vrp->conf), M_NOWAIT); >+ if (!resp) { >+ error = ENOMEM; >+ break; >+ } >+ *((struct ng_vlanrotate_conf *) resp->data) = vrp->conf; >+ break; >+ case NGM_VLANROTATE_SET_CONF: >+ if (msg->header.arglen != sizeof(*pcf)) { >+ error = EINVAL; >+ break; >+ } >+ >+ pcf = (struct ng_vlanrotate_conf *) msg->data; >+ >+ if(pcf->max == 0) pcf->max = vrp->conf.max; /* keep current value */ >+ >+ if(pcf->max > NG_VLANROTATE_MAX_VLANS) error = EINVAL; >+ if(pcf->min > pcf->max) error = EINVAL; >+ if(abs(pcf->rot) >= pcf->max) error = EINVAL; >+ >+ if(error == 0) /* okay */ >+ vrp->conf = *pcf; >+ >+ break; >+ case NGM_VLANROTATE_GET_STAT: >+ case NGM_VLANROTATE_GETCLR_STAT: >+ NG_MKRESPONSE(resp, msg, sizeof(vrp->stat), M_NOWAIT); >+ if (!resp) { >+ error = ENOMEM; >+ break; >+ } >+ *(struct ng_vlanrotate_stat *)resp->data = vrp->stat; >+ if(msg->header.cmd != NGM_VLANROTATE_GETCLR_STAT) >+ break; >+ case NGM_VLANROTATE_CLR_STAT: >+ bzero(&(vrp->stat), sizeof(vrp->stat)); >+ break; >+ default: >+ error = EINVAL; /* unknown command */ >+ break; >+ } >+ break; >+ default: >+ error = EINVAL; /* unknown cookie type */ >+ break; >+ } >+ >+ /* Take care of synchronous response, if any */ >+ NG_RESPOND_MSG(error, node, item, resp); >+ /* Free the message and return */ >+ NG_FREE_MSG(msg); >+ return(error); >+} >+ >+/* >+ * Receive data, and do something with it. >+ * Actually we receive a queue item which holds the data. >+ * If we free the item it will also free the data unless we have >+ * previously disassociated it using the NGI_GET_M() macro. >+ * Possibly send it out on another link after processing. >+ * Possibly do something different if it comes from different >+ * hooks. The caller will never free m, so if we use up this data or >+ * abort we must free it. >+ * >+ * If we want, we may decide to force this data to be queued and reprocessed >+ * at the netgraph NETISR time. >+ * We would do that by setting the HK_QUEUE flag on our hook. We would do that >+ * in the connect() method. >+ */ >+ >+struct ether_vlan_stack_entry { >+ uint16_t proto; >+ uint16_t tag; >+} __packed; >+ >+struct ether_vlan_stack_header { >+ uint8_t dst[ETHER_ADDR_LEN]; >+ uint8_t src[ETHER_ADDR_LEN]; >+ struct ether_vlan_stack_entry vlan_stack[1]; >+} __packed; >+ >+static int >+ng_vlanrotate_gcd(int a, int b) >+{ >+ if (b == 0) >+ return a; >+ else >+ return ng_vlanrotate_gcd(b, a % b); >+} >+ >+#define COPY_VLAN_KEEP_QOS(dst,src) { \ >+ (dst).proto = (src).proto; \ >+ (dst).tag &= ~htons(EVL_VLID_MASK); \ >+ (dst).tag |= (src).tag & htons(EVL_VLID_MASK); \ >+ } while(0) >+ >+static void >+ng_vlanrotate_rotate(struct ether_vlan_stack_entry arr[], int d, int n) >+{ >+ int i, j, k; >+ struct ether_vlan_stack_entry temp; >+ >+ /* for each comensurable slice */ >+ for (i = ng_vlanrotate_gcd(d, n); i-- > 0;) { >+ /* rotate left aka downwards */ >+ COPY_VLAN_KEEP_QOS(temp, arr[i]); >+ j = i; >+ >+ while (1) { >+ k = j + d; >+ if (k >= n) >+ k = k - n; >+ if (k == i) >+ break; >+ COPY_VLAN_KEEP_QOS(arr[j], arr[k]); >+ j = k; >+ } >+ >+ COPY_VLAN_KEEP_QOS(arr[j], temp); >+ } >+} >+ >+#undef COPY_VLAN_KEEP_QOS >+ >+static int >+ng_vlanrotate_rcvdata(hook_p hook, item_p item) >+{ >+ const vlanrotate_p vrp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); >+ struct mbuf *m = NULL; >+ hook_p dst_hook; >+ int8_t rotate; >+ int8_t vlans = 0; >+ int error = ENOSYS; >+ struct ether_vlan_stack_header *evsh; >+ >+ NGI_GET_M(item, m); >+ >+ if(hook == vrp->ordered_hook) { >+ rotate = + vrp->conf.rot; >+ dst_hook = vrp->original_hook; >+ } else if(hook == vrp->original_hook) { >+ rotate = - vrp->conf.rot; >+ dst_hook = vrp->ordered_hook; >+ } else { >+ dst_hook = vrp->original_hook; >+ goto send; /* everything else goes out unmodified */ >+ } >+ >+ if(dst_hook == NULL) { >+ error = ENETDOWN; >+ goto fail; >+ } >+ >+ /* count the vlans */ >+ for(vlans = 0; vlans <= NG_VLANROTATE_MAX_VLANS; vlans++) { >+ size_t expected_len = sizeof(struct ether_vlan_stack_header) + vlans * sizeof(struct ether_vlan_stack_entry); >+ >+ if (m->m_len < expected_len) { >+ m = m_pullup(m, expected_len); >+ if (m == NULL) { >+ error = EINVAL; >+ goto fail; >+ } >+ } >+ >+ evsh = mtod(m, struct ether_vlan_stack_header *); >+ switch(ntohs(evsh->vlan_stack[vlans].proto)) { >+ case ETHERTYPE_VLAN: >+ case ETHERTYPE_QINQ: >+ case 0x9100: >+ break; >+ default: >+ goto out; >+ } >+ } >+out: >+ if(vlans > vrp->conf.max || vlans >= NG_VLANROTATE_MAX_VLANS) { >+ vrp->stat.excessive++; >+ dst_hook = vrp->excessive_hook; >+ goto send; >+ } >+ >+ if((vlans < vrp->conf.min) || (vlans <= abs(rotate))) { >+ vrp->stat.incomplete++; >+ dst_hook = vrp->incomplete_hook; >+ goto send; >+ } >+ vrp->stat.histogram[vlans]++; >+ >+ /* 01234 5 vlans >+ * ----- >+ * 34012 +2 rotate >+ * 12340 +4 rotate >+ * 12340 -1 rotate >+ */ >+ if(rotate == 0) { >+ /* do nothing */ >+ } else if(rotate > 0) { >+ ng_vlanrotate_rotate(evsh->vlan_stack, rotate, vlans); >+ } else { >+ ng_vlanrotate_rotate(evsh->vlan_stack, vlans + rotate, vlans); >+ } >+ >+send: >+ if(dst_hook == NULL) goto fail; >+ NG_FWD_NEW_DATA(error, item, dst_hook, m); >+ return 0; >+ >+fail: >+ vrp->stat.drops ++; >+ if(m != NULL) m_freem(m); >+ NG_FREE_ITEM(item); >+ return (error); >+} >+ >+/* >+ * Do local shutdown processing.. >+ * All our links and the name have already been removed. >+ */ >+static int >+ng_vlanrotate_shutdown(node_p node) >+{ >+ const vlanrotate_p vrp = NG_NODE_PRIVATE(node); >+ >+ NG_NODE_SET_PRIVATE(node, NULL); >+ NG_NODE_UNREF(node); >+ free(vrp, M_NETGRAPH); >+ >+ return (0); >+} >+ >+/* >+ * Hook disconnection >+ * >+ * For this type, removal of the last link destroys the node >+ */ >+static int >+ng_vlanrotate_disconnect(hook_p hook) >+{ >+ const vlanrotate_p vrp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); >+ >+ if(vrp->original_hook == hook) vrp->original_hook = NULL; >+ if(vrp->ordered_hook == hook) vrp->ordered_hook = NULL; >+ if(vrp->excessive_hook == hook) vrp->excessive_hook = NULL; >+ if(vrp->incomplete_hook == hook) vrp->incomplete_hook = NULL; >+ >+ if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0) >+ && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook)))) /* already shutting down? */ >+ ng_rmnode_self(NG_HOOK_NODE(hook)); >+ return (0); >+} >+ > >Index: sys/netgraph/ng_vlan_rotate.h >=================================================================== >--- sys/netgraph/ng_vlan_rotate.h (nonexistent) >+++ sys/netgraph/ng_vlan_rotate.h (working copy) >@@ -0,0 +1,68 @@ >+/* >+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD >+ * >+ * Copyright (c) 2019 IKS Service GmbH >+ * All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ * >+ * Author: Lutz Donnerhacke <lutz@donnerhacke.de> >+ * >+ * $FreeBSD$ >+ */ >+ >+#ifndef _NETGRAPH_NG_VLAN_ROTATE_H_ >+#define _NETGRAPH_NG_VLAN_ROTATE_H_ >+ >+#define NG_VLANROTATE_NODE_TYPE "vlan_rotate" >+#define NGM_VLANROTATE_COOKIE 1568378766 >+ >+/* Hook names */ >+#define NG_VLANROTATE_HOOK_ORDERED "ordered" >+#define NG_VLANROTATE_HOOK_ORIGINAL "original" >+#define NG_VLANROTATE_HOOK_EXCESSIVE "excessive" >+#define NG_VLANROTATE_HOOK_INCOMPLETE "incomplete" >+ >+/* Limits */ >+#define NG_VLANROTATE_MAX_VLANS 10 >+ >+/* Datastructures for netgraph commands */ >+struct ng_vlanrotate_conf { >+ int8_t rot; >+ uint8_t min, max; >+}; >+ >+struct ng_vlanrotate_stat { >+ uint64_t drops, excessive, incomplete; >+ uint64_t histogram[NG_VLANROTATE_MAX_VLANS]; >+}; >+ >+/* Netgraph commands understood by this node type */ >+enum { >+ NGM_VLANROTATE_GET_CONF = 1, >+ NGM_VLANROTATE_SET_CONF, >+ NGM_VLANROTATE_GET_STAT, >+ NGM_VLANROTATE_CLR_STAT, >+ NGM_VLANROTATE_GETCLR_STAT >+}; >+ >+#endif /* _NETGRAPH_NG_VLAN_ROTATE_H_ */ >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 240685
:
207625
|
207732