Hi,

The following adds port protection support to switch(4). The behavior
copies that of bridge(4), where ports can be added to up to 31 protected
domains with a list of IDs using ifconfig(8):

# ifconfig switch0 protected pair1 1,2,..

Domain membership is checked for unicast, flooded (broadcast), and local
(host-network-bound, e.g. a trunk) traffic.

Man page updates will follow in a separate diff.

OK?


Thanks,
Ayaka


Index: net/if_switch.c
===================================================================
RCS file: /cvs/src/sys/net/if_switch.c,v
retrieving revision 1.26
diff -u -p -u -r1.26 if_switch.c
--- net/if_switch.c     28 Apr 2019 22:15:57 -0000      1.26
+++ net/if_switch.c     9 May 2019 22:18:27 -0000
@@ -434,6 +434,7 @@ switch_ioctl(struct ifnet *ifp, unsigned
                }
                breq->ifbr_ifsflags = swpo->swpo_flags;
                breq->ifbr_portno = swpo->swpo_port_no;
+               breq->ifbr_protected = swpo->swpo_protected;
                break;
        case SIOCSIFFLAGS:
                if ((ifp->if_flags & IFF_UP) == IFF_UP)
@@ -467,6 +468,19 @@ switch_ioctl(struct ifnet *ifp, unsigned
                brop->ifbop_last_tc_time.tv_sec = bs->bs_last_tc_time.tv_sec;
                brop->ifbop_last_tc_time.tv_usec = bs->bs_last_tc_time.tv_usec;
                break;
+       case SIOCBRDGSIFPROT:
+               ifs = ifunit(breq->ifbr_ifsname);
+               if (ifs == NULL) {
+                       error = ENOENT;
+                       break;
+               }
+               swpo = (struct switch_port *)ifs->if_switchport;
+               if (swpo == NULL || swpo->swpo_switch != sc) {
+                       error = ESRCH;
+                       break;
+               }
+               swpo->swpo_protected = breq->ifbr_protected;
+               break;
        case SIOCSWGDPID:
        case SIOCSWSDPID:
        case SIOCSWGMAXFLOW:
@@ -560,7 +574,7 @@ switch_port_list(struct switch_softc *sc
                strlcpy(breq.ifbr_name, sc->sc_if.if_xname, IFNAMSIZ);
                breq.ifbr_ifsflags = swpo->swpo_flags;
                breq.ifbr_portno = swpo->swpo_port_no;
-
+               breq.ifbr_protected = swpo->swpo_protected;
                if ((error = copyout((caddr_t)&breq,
                    (caddr_t)(bifc->ifbic_req + n), sizeof(breq))) != 0)
                        goto done;
Index: net/if_switch.h
===================================================================
RCS file: /cvs/src/sys/net/if_switch.h,v
retrieving revision 1.10
diff -u -p -u -r1.10 if_switch.h
--- net/if_switch.h     20 Nov 2016 12:45:26 -0000      1.10
+++ net/if_switch.h     9 May 2019 22:18:27 -0000
@@ -174,6 +174,7 @@ struct switch_port {
        struct timespec                  swpo_appended;
        struct switch_softc             *swpo_switch;
        uint32_t                         swpo_flags;
+       uint32_t                         swpo_protected;
        void                            *swpo_dhcookie;
        void                            (*swop_bk_start)(struct ifnet *);
 };
Index: net/switchofp.c
===================================================================
RCS file: /cvs/src/sys/net/switchofp.c,v
retrieving revision 1.72
diff -u -p -u -r1.72 switchofp.c
--- net/switchofp.c     28 Dec 2018 14:32:47 -0000      1.72
+++ net/switchofp.c     9 May 2019 22:18:28 -0000
@@ -3492,6 +3492,7 @@ swofp_action_output(struct switch_softc 
        struct ofp_action_output        *oao;
        struct switch_port              *swpo;
        struct mbuf                     *mc;
+       uint32_t                        protected = 0;
 
        m->m_pkthdr.csum_flags = 0;
 
@@ -3509,6 +3510,14 @@ swofp_action_output(struct switch_softc 
                }
        }
 
+       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
+               if (swpo->swpo_port_no ==
+                   swpld->swpld_swfcl->swfcl_in_port) {
+                       protected = swpo->swpo_protected;
+                       break;
+               }
+       }
+
        switch (ntohl(oao->ao_port)) {
        case OFP_PORT_CONTROLLER:
                swofp_action_output_controller(sc, mc, swpld,
@@ -3521,7 +3530,8 @@ swofp_action_output(struct switch_softc 
        case OFP_PORT_FLOOD:
                TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
                        if (swpo->swpo_port_no !=
-                           swpld->swpld_swfcl->swfcl_in_port)
+                           swpld->swpld_swfcl->swfcl_in_port &&
+                           (protected & swpo->swpo_protected) == 0)
                                TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
                                    swpo_fwdp_next);
                }
@@ -3543,7 +3553,8 @@ swofp_action_output(struct switch_softc 
                break;
        case OFP_PORT_LOCAL:
                TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if (swpo->swpo_flags & IFBIF_LOCAL) {
+                       if ((swpo->swpo_flags & IFBIF_LOCAL) &&
+                           (protected & swpo->swpo_protected) == 0) {
                                TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
                                    swpo_fwdp_next);
                                break;
@@ -3552,7 +3563,8 @@ swofp_action_output(struct switch_softc 
                break;
        default:
                TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if (swpo->swpo_port_no == ntohl(oao->ao_port))
+                       if (swpo->swpo_port_no == ntohl(oao->ao_port) &&
+                           (protected & swpo->swpo_protected) == 0)
                                TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
                                    swpo_fwdp_next);
                }

Reply via email to