On Wed, Jan 24, 2018 at 11:27:51PM +0000, Tom Smyth wrote:
> Hello, Martin, Remi, All
> Im very excited about this feature, Thanks Martin,
> Please see Comments inline below
> 
> On 23 January 2018 at 18:06, Remi Locherer <remi.loche...@relo.ch> wrote:
> > On Mon, Jan 22, 2018 at 04:23:59PM +0100, Martin Pieuchot wrote:
> >> Diff below adds a new feature to bridge(4), similar to Cisco's Protected
> >> Port but with more possibilities.
> >>
> >> The idea is to prevent traffic to flow between some members of a bridge(4).
> >> For example:
> >>   - you want to prevent some of your servers to talk to each others, or
> >>   - you want employees/students/clients to have access to internet and a
> >>     printer but not to each other, or
> >>   - you want VMs to have access to an uplink but not to each other
> >
> > I think the last example is really useful and makes sense.
> Agreed
> >
> > For the other cases there would most likely be a switch between the other
> > host and the OpenBSD box. Then you need to enforce the policy on that 
> > switch.
> Other examples where it would be useful if the OpenBSD box is terminating
> alot of Tunnels and you want to limit broadcast domains.
> >
> >> With the diff below it is now possible to defined "protected groups".
> >> Interface that are part of such groups cannot send/receive traffic
> >> to/from any other member of the group.
> >
> > Why several protected groups and not just a single one?
> Having multiple protected groups can be useful in the following circumstances:
> Where you want to isolate clients / vms from each other,
> and where you have 2 redundant up-link ports in the bridge that could other 
> wise
> create a loop.
> (where spanning tree cannot be deployed (due to incompatible or
> limited switches)

Wouldn't this duplicate BUM traffic? In this situation I would try a setup with
trunk(4) for the uplinks. At least the failover mode should work if your
switches have a limited feature set.

> e.g
> a) loop prevention in 2 up link ports on a bridge
> so if the 2 up-link  ports are added to the same protected group they cannot
> form a loop as the 2 up-links are isolated from each other
> Uplink ports would be em1 and em2 and we would add them to protected group1
> em1 and em2 cannot communicate with each other and cant create a loop
> b)preventing vms from talking to each other by adding them to another 
> protected
> group
> e.g.
> tap1 and tap2  would be added to protected group 2
> so tap1 and tap2 would be isolated from each other, and because they are 
> members
> of a different protected group to em1 and em2 in the same bridge they
> can communicate
> freely with either em1 or em2
> 
> I have used this technique on certain Layer 2 networks where STP was
> not possible or
> desirable,, and it would give the administrator granular control
> of traffic flow  in the bridge
> Other Added benefits
> (control broadcast domains etc)
> increase security  for access networks (prevent rogue dhcp Servers)
> 
> I hope this helps and Im really excited with this diff :)
> Thanks Guys
> 
> 
> >
> >>
> >> In the example below, em1 and em2 can only send/receive traffic through
> >> em0 because they are both in the protected group 2.
> >>
> >> bridge0: flags=41<UP,RUNNING>
> >>         index 9 llprio 3
> >>         groups: bridge
> >>         priority 32768 hellotime 2 fwddelay 15 maxage 20 holdcnt 6 proto 
> >> rstp
> >>         designated: id 00:00:00:00:00:00 priority 0
> >>         em0 flags=3<LEARNING,DISCOVER>
> >>                 port 6 ifpriority 0 ifcost 0
> >>         em1 flags=3<LEARNING,DISCOVER>
> >>                 port 7 ifpriority 0 ifcost 0 protected 2
> >>         em2 flags=3<LEARNING,DISCOVER>
> >>                 port 8 ifpriority 0 ifcost 0 protected 2
> >>
> >> Adding an interface to a protected group is as simple as:
> >>
> >>   # ifconfig bridge0 protected em1 2
> >>
> >> Removing it:
> >>
> >>   # ifconfig bridge0 -protected em1
> >>
> >> Comments?  Oks?
> >>
> >> Index: sys/net/if_bridge.c
> >> ===================================================================
> >> RCS file: /cvs/src/sys/net/if_bridge.c,v
> >> retrieving revision 1.301
> >> diff -u -p -r1.301 if_bridge.c
> >> --- sys/net/if_bridge.c       10 Jan 2018 23:50:39 -0000      1.301
> >> +++ sys/net/if_bridge.c       22 Jan 2018 14:27:41 -0000
> >> @@ -409,6 +409,7 @@ bridge_ioctl(struct ifnet *ifp, u_long c
> >>               }
> >>               req->ifbr_ifsflags = p->bif_flags;
> >>               req->ifbr_portno = p->ifp->if_index & 0xfff;
> >> +             req->ifbr_protected = p->bif_protected;
> >>               if (p->bif_flags & IFBIF_STP) {
> >>                       bp = p->bif_stp;
> >>                       req->ifbr_state = bstp_getstate(bs, bp);
> >> @@ -496,6 +497,19 @@ bridge_ioctl(struct ifnet *ifp, u_long c
> >>               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(req->ifbr_ifsname);
> >> +             if (ifs == NULL) {
> >> +                     error = ENOENT;
> >> +                     break;
> >> +             }
> >> +             p = (struct bridge_iflist *)ifs->if_bridgeport;
> >> +             if (p == NULL || p->bridge_sc != sc) {
> >> +                     error = ESRCH;
> >> +                     break;
> >> +             }
> >> +             p->bif_protected = req->ifbr_protected;
> >> +             break;
> >>       case SIOCBRDGRTS:
> >>       case SIOCBRDGGCACHE:
> >>       case SIOCBRDGGPRI:
> >> @@ -594,6 +608,7 @@ bridge_bifconf(struct bridge_softc *sc,
> >>               strlcpy(breq->ifbr_ifsname, p->ifp->if_xname, IFNAMSIZ);
> >>               breq->ifbr_ifsflags = p->bif_flags;
> >>               breq->ifbr_portno = p->ifp->if_index & 0xfff;
> >> +             breq->ifbr_protected = p->bif_protected;
> >>               if (p->bif_flags & IFBIF_STP) {
> >>                       bp = p->bif_stp;
> >>                       breq->ifbr_state = bstp_getstate(sc->sc_stp, bp);
> >> @@ -848,6 +863,7 @@ bridgeintr_frame(struct bridge_softc *sc
> >>       struct bridge_rtnode *dst_p;
> >>       struct ether_addr *dst, *src;
> >>       struct ether_header eh;
> >> +     u_int32_t protected;
> >>       int len;
> >>
> >>
> >> @@ -960,6 +976,7 @@ bridgeintr_frame(struct bridge_softc *sc
> >>               bridge_broadcast(sc, src_if, &eh, m);
> >>               return;
> >>       }
> >> +     protected = ifl->bif_protected;
> >>
> >>       /*
> >>        * At this point, we're dealing with a unicast frame going to a
> >> @@ -975,6 +992,14 @@ bridgeintr_frame(struct bridge_softc *sc
> >>               m_freem(m);
> >>               return;
> >>       }
> >> +     /*
> >> +      * Do not transmit if both ports are part of the same protected
> >> +      * group.
> >> +      */
> >> +     if (protected != 0 && protected == ifl->bif_protected) {
> >> +             m_freem(m);
> >> +             return;
> >> +     }
> >>       if (bridge_filterrule(&ifl->bif_brlout, &eh, m) == BRL_ACTION_BLOCK) 
> >> {
> >>               m_freem(m);
> >>               return;
> >> @@ -1159,6 +1184,10 @@ bridge_broadcast(struct bridge_softc *sc
> >>       struct mbuf *mc;
> >>       struct ifnet *dst_if;
> >>       int len, used = 0;
> >> +     u_int32_t protected;
> >> +
> >> +     p = (struct bridge_iflist *)ifp->if_bridgeport;
> >> +     protected = p->bif_protected;
> >>
> >>       TAILQ_FOREACH(p, &sc->sc_iflist, next) {
> >>               dst_if = p->ifp;
> >> @@ -1177,6 +1206,13 @@ bridge_broadcast(struct bridge_softc *sc
> >>               /* Drop non-IP frames if the appropriate flag is set. */
> >>               if (p->bif_flags & IFBIF_BLOCKNONIP &&
> >>                   bridge_blocknonip(eh, m))
> >> +                     continue;
> >> +
> >> +             /*
> >> +              * Do not transmit if both ports are part of the same
> >> +              * protected group.
> >> +              */
> >> +             if (protected != 0 && protected == p->bif_protected)
> >>                       continue;
> >>
> >>               if (bridge_filterrule(&p->bif_brlout, eh, m) == 
> >> BRL_ACTION_BLOCK)
> >> Index: sys/net/if_bridge.h
> >> ===================================================================
> >> RCS file: /cvs/src/sys/net/if_bridge.h,v
> >> retrieving revision 1.55
> >> diff -u -p -r1.55 if_bridge.h
> >> --- sys/net/if_bridge.h       20 Jan 2017 05:03:48 -0000      1.55
> >> +++ sys/net/if_bridge.h       22 Jan 2018 15:13:07 -0000
> >> @@ -46,6 +46,7 @@ struct ifbreq {
> >>       char            ifbr_ifsname[IFNAMSIZ]; /* member ifs name */
> >>       u_int32_t       ifbr_ifsflags;          /* member ifs flags */
> >>       u_int32_t       ifbr_portno;            /* member port number */
> >> +     u_int32_t       ifbr_protected;         /* protected group number */
> >>
> >>       u_int8_t        ifbr_state;             /* member stp state */
> >>       u_int8_t        ifbr_priority;          /* member stp priority */
> >> @@ -398,6 +399,7 @@ struct bridge_iflist {
> >>       struct brl_head                 bif_brlout;     /* output rules */
> >>       struct                          ifnet *ifp;     /* member interface 
> >> */
> >>       u_int32_t                       bif_flags;      /* member flags */
> >> +     u_int32_t                       bif_protected;  /* protected group */
> >>       void                            *bif_dhcookie;
> >>  };
> >>  #define bif_state                    bif_stp->bp_state
> >> Index: sys/sys/sockio.h
> >> ===================================================================
> >> RCS file: /cvs/src/sys/sys/sockio.h,v
> >> retrieving revision 1.72
> >> diff -u -p -r1.72 sockio.h
> >> --- sys/sys/sockio.h  24 Oct 2017 09:36:13 -0000      1.72
> >> +++ sys/sys/sockio.h  22 Jan 2018 14:09:09 -0000
> >> @@ -89,6 +89,7 @@
> >>  #define      SIOCBRDGDADDR    _IOW('i', 71, struct ifbareq)  /* delete 
> >> addr */
> >>  #define      SIOCBRDGFLUSH    _IOW('i', 72, struct ifbreq)   /* flush 
> >> addr cache */
> >>  #define      SIOCBRDGADDL     _IOW('i', 73, struct ifbreq)   /* add local 
> >> port */
> >> +#define      SIOCBRDGSIFPROT  _IOW('i', 74, struct ifbreq)   /* set 
> >> protected grp */
> >>
> >>  #define SIOCBRDGARL   _IOW('i', 77, struct ifbrlreq) /* add bridge rule */
> >>  #define SIOCBRDGFRL   _IOW('i', 78, struct ifbrlreq) /* flush brdg rules 
> >> */
> >> Index: sbin/ifconfig/brconfig.c
> >> ===================================================================
> >> RCS file: /cvs/src/sbin/ifconfig/brconfig.c,v
> >> retrieving revision 1.16
> >> diff -u -p -r1.16 brconfig.c
> >> --- sbin/ifconfig/brconfig.c  31 Jul 2017 02:32:11 -0000      1.16
> >> +++ sbin/ifconfig/brconfig.c  22 Jan 2018 14:30:38 -0000
> >> @@ -336,6 +336,8 @@ bridge_list(char *delim)
> >>               printf("port %u ifpriority %u ifcost %u",
> >>                   reqp->ifbr_portno, reqp->ifbr_priority,
> >>                   reqp->ifbr_path_cost);
> >> +             if (reqp->ifbr_protected)
> >> +                     printf(" protected %u", reqp->ifbr_protected);
> >>               if (reqp->ifbr_ifsflags & IFBIF_STP)
> >>                       printf(" %s role %s",
> >>                           stpstates[reqp->ifbr_state],
> >> @@ -452,6 +454,41 @@ bridge_priority(const char *arg, int d)
> >>       bp.ifbrp_prio = v;
> >>       if (ioctl(s, SIOCBRDGSPRI, (caddr_t)&bp) < 0)
> >>               err(1, "%s", name);
> >> +}
> >> +
> >> +void
> >> +bridge_protect(const char *ifname, const char *val)
> >> +{
> >> +     struct ifbreq breq;
> >> +     unsigned long v;
> >> +     char *endptr;
> >> +
> >> +     strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
> >> +     strlcpy(breq.ifbr_ifsname, ifname, sizeof(breq.ifbr_ifsname));
> >> +
> >> +     errno = 0;
> >> +     v = strtoul(val, &endptr, 0);
> >> +     if (val[0] == '\0' || endptr[0] != '\0' || v == 0 || v > UINT32_MAX 
> >> ||
> >> +         (errno == ERANGE && v == ULONG_MAX))
> >> +             err(1, "invalid arg for protected group: %s", val);
> >> +     breq.ifbr_protected = v;
> >> +
> >> +     if (ioctl(s, SIOCBRDGSIFPROT, (caddr_t)&breq) < 0)
> >> +             err(1, "%s: %s", name, val);
> >> +}
> >> +
> >> +void
> >> +bridge_unprotect(const char *ifname, int d)
> >> +{
> >> +     struct ifbreq breq;
> >> +
> >> +     strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
> >> +     strlcpy(breq.ifbr_ifsname, ifname, sizeof(breq.ifbr_ifsname));
> >> +
> >> +     breq.ifbr_protected = 0;
> >> +
> >> +     if (ioctl(s, SIOCBRDGSIFPROT, (caddr_t)&breq) < 0)
> >> +             err(1, "%s: %d", name, 0);
> >>  }
> >>
> >>  void
> >> Index: sbin/ifconfig/brconfig.h
> >> ===================================================================
> >> RCS file: /cvs/src/sbin/ifconfig/brconfig.h,v
> >> retrieving revision 1.12
> >> diff -u -p -r1.12 brconfig.h
> >> --- sbin/ifconfig/brconfig.h  16 Jan 2018 10:33:55 -0000      1.12
> >> +++ sbin/ifconfig/brconfig.h  22 Jan 2018 14:12:39 -0000
> >> @@ -52,6 +52,8 @@ void bridge_addrs(const char *, int);
> >>  void bridge_hellotime(const char *, int);
> >>  void bridge_fwddelay(const char *, int);
> >>  void bridge_maxage(const char *, int);
> >> +void bridge_protect(const char *, const char *);
> >> +void bridge_unprotect(const char *, int);
> >>  void bridge_proto(const char *, int);
> >>  void bridge_ifprio(const char *, const char *);
> >>  void bridge_ifcost(const char *, const char *);
> >> Index: sbin/ifconfig/ifconfig.8
> >> ===================================================================
> >> RCS file: /cvs/src/sbin/ifconfig/ifconfig.8,v
> >> retrieving revision 1.292
> >> diff -u -p -r1.292 ifconfig.8
> >> --- sbin/ifconfig/ifconfig.8  16 Jan 2018 10:33:55 -0000      1.292
> >> +++ sbin/ifconfig/ifconfig.8  22 Jan 2018 15:11:32 -0000
> >> @@ -662,6 +662,13 @@ The default is 100 entries.
> >>  .It Cm maxage Ar time
> >>  Set the time (in seconds) that a spanning tree protocol configuration is 
> >> valid.
> >>  Defaults to 20 seconds, minimum of 6, maximum of 40.
> >> +.It Cm protected Ar interface Ar id
> >> +Put
> >> +.Ar interface
> >> +in protected mode.
> >> +A protected interface does not forward traffic to any other protected 
> >> interface
> >> +having the same
> >> +.Ar id .
> >>  .It Cm proto Ar value
> >>  Force the spanning tree protocol version.
> >>  The available values are
> >> Index: sbin/ifconfig/ifconfig.c
> >> ===================================================================
> >> RCS file: /cvs/src/sbin/ifconfig/ifconfig.c,v
> >> retrieving revision 1.353
> >> diff -u -p -r1.353 ifconfig.c
> >> --- sbin/ifconfig/ifconfig.c  16 Jan 2018 10:33:55 -0000      1.353
> >> +++ sbin/ifconfig/ifconfig.c  22 Jan 2018 14:17:17 -0000
> >> @@ -472,6 +472,8 @@ const struct      cmd {
> >>       { "-edge",      NEXTARG,        0,              unsetedge },
> >>       { "autoedge",   NEXTARG,        0,              setautoedge },
> >>       { "-autoedge",  NEXTARG,        0,              unsetautoedge },
> >> +     { "protected",  NEXTARG2,       0,              NULL, bridge_protect 
> >> },
> >> +     { "-protected", NEXTARG,        0,              bridge_unprotect },
> >>       { "ptp",        NEXTARG,        0,              setptp },
> >>       { "-ptp",       NEXTARG,        0,              unsetptp },
> >>       { "autoptp",    NEXTARG,        0,              setautoptp },
> >
> 
> 
> 
> -- 
> Kindest regards,
> Tom Smyth
> 
> Mobile: +353 87 6193172
> The information contained in this E-mail is intended only for the
> confidential use of the named recipient. If the reader of this message
> is not the intended recipient or the person responsible for
> delivering it to the recipient, you are hereby notified that you have
> received this communication in error and that any review,
> dissemination or copying of this communication is strictly prohibited.
> If you have received this in error, please notify the sender
> immediately by telephone at the number above and erase the message
> You are requested to carry out your own virus check before
> opening any attachment.

Reply via email to