summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sbin/ifconfig/brconfig.c120
-rw-r--r--sbin/ifconfig/brconfig.h6
-rw-r--r--sbin/ifconfig/ifconfig.c6
-rw-r--r--sys/net/if_bridge.c6
-rw-r--r--sys/net/if_bridge.h18
-rw-r--r--sys/net/if_switch.c137
-rw-r--r--sys/net/switchofp.c64
-rw-r--r--sys/sys/sockio.h13
8 files changed, 348 insertions, 22 deletions
diff --git a/sbin/ifconfig/brconfig.c b/sbin/ifconfig/brconfig.c
index 1dc1a50b5a5..c8f3be8c2b6 100644
--- a/sbin/ifconfig/brconfig.c
+++ b/sbin/ifconfig/brconfig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: brconfig.c,v 1.9 2015/07/18 06:50:24 rzalamena Exp $ */
+/* $OpenBSD: brconfig.c,v 1.10 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -56,10 +56,11 @@ void bridge_list(char *);
void bridge_cfg(const char *);
void bridge_badrule(int, char **, int);
void bridge_showrule(struct ifbrlreq *);
+int is_switch(char *);
#define IFBAFBITS "\020\1STATIC"
#define IFBIFBITS \
-"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN"
+"\020\1LEARNING\2DISCOVER\3BLOCKNONIP\4STP\5EDGE\6AUTOEDGE\7PTP\10AUTOPTP\11SPAN\15LOCAL"
#define PV2ID(pv, epri, eaddr) do { \
epri = pv >> 48; \
@@ -189,6 +190,24 @@ unsetautoptp(const char *val, int d)
bridge_ifclrflag(val, IFBIF_BSTP_AUTOPTP);
}
+void
+addlocal(const char *ifsname, int d)
+{
+ struct ifbreq breq;
+
+ if (strncmp(ifsname, "vether", (sizeof("vether") - 1)) != 0)
+ errx(1, "only vether can be local interface");
+
+ /* Add local */
+ strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
+ strlcpy(breq.ifbr_ifsname, ifsname, sizeof(breq.ifbr_ifsname));
+ if (ioctl(s, SIOCBRDGADDL, (caddr_t)&breq) < 0) {
+ if (errno == EEXIST)
+ errx(1, "%s: local port exists already");
+ else
+ err(1, "%s: ioctl SIOCBRDGADDL %s", name, ifsname);
+ }
+}
void
bridge_ifsetflag(const char *ifsname, u_int32_t flag)
@@ -702,7 +721,7 @@ bridge_status(void)
struct ifreq ifr;
struct ifbrparam bp1, bp2;
- if (!is_bridge(name))
+ if (!is_bridge(name) || is_switch(name))
return;
strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
@@ -968,4 +987,99 @@ bridge_badrule(int argc, char *argv[], int ln)
fprintf(stderr, "\n");
}
+int
+is_switch(char *swname)
+{
+ struct ifbrparam bp;
+
+ strlcpy(bp.ifbrp_name, swname, sizeof(bp.ifbrp_name));
+ if (ioctl(s, SIOCSWGDPID, (caddr_t)&bp) < 0)
+ return (0);
+
+ return (1);
+}
+
+void
+switch_cfg(char *delim)
+{
+ struct ifbrparam bp;
+
+ strlcpy(bp.ifbrp_name, name, sizeof(bp.ifbrp_name));
+ if (ioctl(s, SIOCSWGDPID, (caddr_t)&bp) < 0)
+ err(1, "%s", name);
+
+ printf("%sdatapath-id 0x%016llx\n", delim, bp.ifbrp_datapath);
+
+ strlcpy(bp.ifbrp_name, name, sizeof(bp.ifbrp_name));
+ if (ioctl(s, SIOCSWGFLOWMAX, (caddr_t)&bp) < 0)
+ err(1, "%s", name);
+
+ printf("%smax flows per table %d\n", delim, bp.ifbrp_maxflow);
+
+ strlcpy(bp.ifbrp_name, name, sizeof(bp.ifbrp_name));
+ if (ioctl(s, SIOCSWGMAXGROUP, (caddr_t)&bp) < 0)
+ err(1, "%s", name);
+
+ printf("%smax groups %d\n", delim, bp.ifbrp_maxgroup);
+}
+
+void
+switch_status(void)
+{
+ struct ifreq ifr;
+ struct ifbrparam bp1, bp2;
+
+ if (!is_switch(name))
+ return;
+
+ strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0)
+ return;
+
+ switch_cfg("\t");
+
+ bridge_list("\t");
+
+ if (aflag && !ifaliases)
+ return;
+}
+
+void
+switch_datapathid(const char *arg, int d)
+{
+ struct ifbrparam bp;
+ uint64_t newdpid;
+ char *endptr;
+
+ errno = 0;
+ newdpid = strtoll(arg, &endptr, 0);
+ if (arg[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
+ errx(1, "invalid arg for datapath-id: %s", arg);
+
+ strlcpy(bp.ifbrp_name, name, sizeof(bp.ifbrp_name));
+ bp.ifbrp_datapath = newdpid;
+ if (ioctl(s, SIOCSWSDPID, (caddr_t)&bp) < 0)
+ err(1, "%s", name);
+}
+
+void
+switch_portno(const char *ifname, const char *val)
+{
+ struct ifbreq breq;
+ uint32_t newportidx;
+ char *endptr;
+
+ strlcpy(breq.ifbr_name, name, sizeof(breq.ifbr_name));
+ strlcpy(breq.ifbr_ifsname, ifname, sizeof(breq.ifbr_ifsname));
+
+ errno = 0;
+ newportidx = strtol(val, &endptr, 0);
+ if (val[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
+ errx(1, "invalid arg for portidx: %s", val);
+
+ breq.ifbr_portno = newportidx;
+ if (ioctl(s, SIOCSWSPORTNO, (caddr_t)&breq) < 0)
+ err(1, "%s", name);
+}
+
#endif
diff --git a/sbin/ifconfig/brconfig.h b/sbin/ifconfig/brconfig.h
index b1eb195947d..ee68feb411b 100644
--- a/sbin/ifconfig/brconfig.h
+++ b/sbin/ifconfig/brconfig.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: brconfig.h,v 1.10 2016/05/08 08:56:59 mpi Exp $ */
+/* $OpenBSD: brconfig.h,v 1.11 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org>
@@ -37,6 +37,7 @@ void setptp(const char *, int);
void unsetptp(const char *, int);
void setautoptp(const char *, int);
void unsetautoptp(const char *, int);
+void addlocal(const char *, int);
void bridge_add(const char *, int);
void bridge_delete(const char *, int);
@@ -64,6 +65,9 @@ void bridge_flushrule(const char *, int);
int is_bridge(char *);
void bridge_status(void);
int bridge_rule(int, char **, int);
+void switch_status(void);
+void switch_datapathid(const char *, int);
+void switch_portno(const char *, const char *);
#define IFFBITS \
"\024\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6NOTRAILERS" \
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 91795dd19f2..7b53792682c 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ifconfig.c,v 1.328 2016/08/31 13:32:27 stsp Exp $ */
+/* $OpenBSD: ifconfig.c,v 1.329 2016/09/02 10:01:36 goda Exp $ */
/* $NetBSD: ifconfig.c,v 1.40 1997/10/01 02:19:43 enami Exp $ */
/*
@@ -516,6 +516,9 @@ const struct cmd {
{ "-roaming", 0, 0, umb_roaming },
{ "patch", NEXTARG, 0, setpair },
{ "-patch", 1, 0, unsetpair },
+ { "datapathid", NEXTARG, 0, switch_datapathid },
+ { "portno", NEXTARG2, 0, NULL, switch_portno },
+ { "addlocal", NEXTARG, 0, addlocal },
#else /* SMALL */
{ "powersave", NEXTARG0, 0, setignore },
{ "priority", NEXTARG, 0, setignore },
@@ -3130,6 +3133,7 @@ status(int link, struct sockaddr_dl *sdl, int ls)
phys_status(0);
#ifndef SMALL
bridge_status();
+ switch_status();
#endif
}
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index ca79aaf0646..80c4b7e67ec 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.282 2016/09/01 10:06:33 goda Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.283 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -117,11 +117,7 @@ void bridge_span(struct bridge_softc *, struct mbuf *);
void bridge_stop(struct bridge_softc *);
void bridge_init(struct bridge_softc *);
int bridge_bifconf(struct bridge_softc *, struct ifbifconf *);
-
int bridge_blocknonip(struct ether_header *, struct mbuf *);
-struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *,
- struct ether_header *, struct mbuf *m);
-int bridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *);
void bridge_ifinput(struct ifnet *, struct mbuf *);
int bridge_dummy_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
diff --git a/sys/net/if_bridge.h b/sys/net/if_bridge.h
index f7d8c97a974..df1a3b9f534 100644
--- a/sys/net/if_bridge.h
+++ b/sys/net/if_bridge.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.h,v 1.49 2016/09/01 10:06:33 goda Exp $ */
+/* $OpenBSD: if_bridge.h,v 1.50 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -45,7 +45,7 @@ struct ifbreq {
char ifbr_name[IFNAMSIZ]; /* bridge ifs name */
char ifbr_ifsname[IFNAMSIZ]; /* member ifs name */
u_int32_t ifbr_ifsflags; /* member ifs flags */
- u_int8_t ifbr_portno; /* member port number */
+ u_int32_t ifbr_portno; /* member port number */
u_int8_t ifbr_state; /* member stp state */
u_int8_t ifbr_priority; /* member stp priority */
@@ -71,7 +71,8 @@ struct ifbreq {
#define IFBIF_BSTP_PTP 0x0040 /* member stp ptp */
#define IFBIF_BSTP_AUTOPTP 0x0080 /* member stp autoptp enabled */
#define IFBIF_SPAN 0x0100 /* ifs is a span port (ro) */
-#define IFBIF_RO_MASK 0xff00 /* read only bits */
+#define IFBIF_LOCAL 0x1000 /* local port in switch(4) */
+#define IFBIF_RO_MASK 0x0f00 /* read only bits */
/* SIOCBRDGFLUSH */
#define IFBF_FLUSHDYN 0x0 /* flush dynamic addresses only */
@@ -152,6 +153,8 @@ struct ifbrparam {
u_int8_t ifbrpu_maxage; /* max age (sec) */
u_int8_t ifbrpu_proto; /* bridge protocol */
u_int8_t ifbrpu_txhc; /* bpdu tx holdcount */
+ u_int64_t ifbrpu_datapath; /* datapath-id */
+ u_int32_t ifbrpu_maxgroup; /* group size */
} ifbrp_ifbrpu;
};
#define ifbrp_csize ifbrp_ifbrpu.ifbrpu_csize
@@ -162,6 +165,9 @@ struct ifbrparam {
#define ifbrp_hellotime ifbrp_ifbrpu.ifbrpu_hellotime
#define ifbrp_fwddelay ifbrp_ifbrpu.ifbrpu_fwddelay
#define ifbrp_maxage ifbrp_ifbrpu.ifbrpu_maxage
+#define ifbrp_datapath ifbrp_ifbrpu.ifbrpu_datapath
+#define ifbrp_maxflow ifbrp_ifbrpu.ifbrpu_csize
+#define ifbrp_maxgroup ifbrp_ifbrpu.ifbrpu_maxgroup
/* Protocol versions */
#define BSTP_PROTO_ID 0x00
@@ -472,8 +478,12 @@ void bridge_timer(void *);
u_int8_t bridge_filterrule(struct brl_head *, struct ether_header *,
struct mbuf *);
void bridge_flushrule(struct bridge_iflist *);
-void bridge_fragment(struct bridge_softc *, struct ifnet *,
+
+struct mbuf *bridge_ip(struct bridge_softc *, int, struct ifnet *,
+ struct ether_header *, struct mbuf *);
+void bridge_fragment(struct bridge_softc *, struct ifnet *,
struct ether_header *, struct mbuf *);
+int bridge_ifenqueue(struct bridge_softc *, struct ifnet *, struct mbuf *);
#endif /* _KERNEL */
#endif /* _NET_IF_BRIDGE_H_ */
diff --git a/sys/net/if_switch.c b/sys/net/if_switch.c
index b8c3529cee7..8f481583981 100644
--- a/sys/net/if_switch.c
+++ b/sys/net/if_switch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_switch.c,v 1.1 2016/09/01 10:06:33 goda Exp $ */
+/* $OpenBSD: if_switch.c,v 1.2 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
@@ -121,6 +121,9 @@ struct mbuf
*switch_flow_classifier_ether(struct mbuf *, int *,
struct switch_flow_classify *);
struct mbuf
+ *switch_flow_classifier_tunnel(struct mbuf *, int *,
+ struct switch_flow_classify *);
+struct mbuf
*switch_flow_classifier(struct mbuf *, uint32_t,
struct switch_flow_classify *);
void switch_flow_classifier_dump(struct switch_softc *,
@@ -212,6 +215,8 @@ switch_clone_destroy(struct ifnet *ifp)
TAILQ_FOREACH_SAFE(swpo, &sc->sc_swpo_list, swpo_list_next, tp) {
if ((ifs = if_get(swpo->swpo_ifindex)) != NULL) {
+ if (swpo->swpo_flags & IFBIF_LOCAL)
+ switch_port_unset_local(sc, swpo);
ifs->if_switchport = NULL;
ifpromisc(ifs, 0);
if_ih_remove(ifs, switch_input, NULL);
@@ -307,6 +312,99 @@ discard:
}
int
+switch_port_set_local(struct switch_softc *sc, struct switch_port *swpo)
+{
+ struct switch_port *tswpo;
+ struct ifreq ifreq;
+ struct ifnet *ifs;
+ int error = 0, re_up = 0;
+
+ /*
+ * Only one local interface can exist per switch device.
+ */
+ TAILQ_FOREACH(tswpo, &sc->sc_swpo_list, swpo_list_next) {
+ if (tswpo->swpo_flags & IFBIF_LOCAL)
+ return (EEXIST);
+ }
+
+ ifs = if_get(swpo->swpo_ifindex);
+ if (ifs == NULL)
+ return (ENOENT);
+
+ if (ifs->if_flags & IFF_UP) {
+ re_up = 1;
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, ifs->if_xname, IFNAMSIZ);
+ ifs->if_flags &= ~IFF_UP;
+ ifreq.ifr_flags = ifs->if_flags;
+ error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq);
+ if (error)
+ goto error;
+ }
+
+ swpo->swpo_flags |= IFBIF_LOCAL;
+ swpo->swpo_port_no = OFP_PORT_LOCAL;
+ swpo->swop_bk_start = ifs->if_start;
+ ifs->if_start = switch_port_ifb_start;
+
+ if (re_up) {
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, ifs->if_xname, IFNAMSIZ);
+ ifs->if_flags &= IFF_UP;
+ ifreq.ifr_flags = ifs->if_flags;
+ error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq);
+ if (error)
+ goto error;
+ }
+
+ error:
+ if_put(ifs);
+ return (error);
+}
+
+int
+switch_port_unset_local(struct switch_softc *sc, struct switch_port *swpo)
+{
+ struct ifreq ifreq;
+ struct ifnet *ifs;
+ int error = 0, re_up = 0;
+
+ ifs = if_get(swpo->swpo_ifindex);
+ if (ifs == NULL)
+ return (ENOENT);
+
+ if (ifs->if_flags & IFF_UP) {
+ re_up = 1;
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, ifs->if_xname, IFNAMSIZ);
+ ifs->if_flags &= ~IFF_UP;
+ ifreq.ifr_flags = ifs->if_flags;
+ error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq);
+ if (error)
+ goto error;
+ }
+
+ swpo->swpo_flags &= ~IFBIF_LOCAL;
+ swpo->swpo_port_no = swofp_assign_portno(sc, ifs->if_index);
+ ifs->if_start = swpo->swop_bk_start;
+ swpo->swop_bk_start = NULL;
+
+ if (re_up) {
+ memset(&ifreq, 0, sizeof(ifreq));
+ strlcpy(ifreq.ifr_name, ifs->if_xname, IFNAMSIZ);
+ ifs->if_flags &= IFF_UP;
+ ifreq.ifr_flags = ifs->if_flags;
+ error = (*ifs->if_ioctl)(ifs, SIOCSIFFLAGS, (caddr_t)&ifreq);
+ if (error)
+ goto error;
+ }
+
+ error:
+ if_put(ifs);
+ return (error);
+}
+
+int
switch_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
{
struct ifbaconf *baconf = (struct ifbaconf *)data;
@@ -335,6 +433,24 @@ switch_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
case SIOCBRDGIFS:
error = switch_port_list(sc, (struct ifbifconf *)data);
break;
+ case SIOCBRDGADDL:
+ if ((error = suser(curproc, 0)) != 0)
+ break;
+ error = switch_port_add(sc, (struct ifbreq *)data);
+ if (error && error != EEXIST)
+ break;
+ 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;
+ }
+ error = switch_port_set_local(sc, swpo);
+ break;
case SIOCBRDGGIFFLGS:
ifs = ifunit(breq->ifbr_ifsname);
if (ifs == NULL) {
@@ -381,6 +497,13 @@ switch_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
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 SIOCSWGDPID:
+ case SIOCSWSDPID:
+ case SIOCSWGFLOWMAX:
+ case SIOCSWGMAXGROUP:
+ case SIOCSWSPORTNO:
+ error = swofp_ioctl(ifp, cmd, data);
+ break;
default:
error = ENOTTY;
break;
@@ -521,6 +644,8 @@ switch_port_del(struct switch_softc *sc, struct ifbreq *req)
}
if (swpo) {
+ if (swpo->swpo_flags & IFBIF_LOCAL)
+ switch_port_unset_local(sc, swpo);
ifs->if_switchport = NULL;
ifpromisc(ifs, 0);
if_ih_remove(ifs, switch_input, NULL);
@@ -661,11 +786,17 @@ switch_port_egress(struct switch_softc *sc, struct switch_fwdp_queue *fwdp_q,
len += ETHER_VLAN_ENCAP_LEN;
#endif
- if (((len - ETHER_HDR_LEN) > dst_if->if_mtu))
+ /*
+ * Only if egress port has local port capabilities, it doesn't
+ * need fragment because a frame sends up local network stack.
+ */
+ if (!(swpo->swpo_flags & IFBIF_LOCAL) &&
+ ((len - ETHER_HDR_LEN) > dst_if->if_mtu))
bridge_fragment((struct bridge_softc *)sc,
dst_if, &eh, mc);
else
- switch_ifenqueue(sc, dst_if, mc, 0);
+ switch_ifenqueue(sc, dst_if, mc,
+ (swpo->swpo_flags & IFBIF_LOCAL));
out:
if_put(dst_if);
diff --git a/sys/net/switchofp.c b/sys/net/switchofp.c
index cd8e7408e96..6b9102cf59e 100644
--- a/sys/net/switchofp.c
+++ b/sys/net/switchofp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: switchofp.c,v 1.1 2016/09/01 10:06:33 goda Exp $ */
+/* $OpenBSD: switchofp.c,v 1.2 2016/09/02 10:01:36 goda Exp $ */
/*
* Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
@@ -1024,9 +1024,53 @@ swofp_assign_portno(struct switch_softc *sc, uint32_t req)
int
swofp_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data)
{
+ struct switch_softc *sc = ifp->if_softc;
+ struct swofp_ofs *swofs = sc->sc_ofs;
+ struct ifbrparam *bparam = (struct ifbrparam *)data;
+ struct ifbreq *breq = (struct ifbreq *)data;
+ struct switch_port *swpo;
+ struct ifnet *ifs;
int error = 0;
switch (cmd) {
+ case SIOCSWGDPID:
+ memcpy(&bparam->ifbrp_datapath, &swofs->swofs_datapath_id,
+ sizeof(uint64_t));
+ break;
+ case SIOCSWSDPID:
+ if ((error = suser(curproc, 0)) != 0)
+ break;
+ memcpy(&swofs->swofs_datapath_id, &bparam->ifbrp_datapath,
+ sizeof(uint64_t));
+ break;
+ case SIOCSWGFLOWMAX:
+ bparam->ifbrp_maxflow = swofs->swofs_flow_max_entry;
+ break;
+ case SIOCSWGMAXGROUP:
+ bparam->ifbrp_maxgroup = swofs->swofs_group_table_num;
+ break;
+ case SIOCSWSPORTNO:
+ if ((error = suser(curproc, 0)) != 0)
+ break;
+
+ if (breq->ifbr_portno >= OFP_PORT_MAX)
+ return (EINVAL);
+
+ if ((ifs = ifunit(breq->ifbr_ifsname)) == NULL)
+ return (ENOENT);
+
+ if (ifs->if_switchport == NULL)
+ return (ENOENT);
+
+ TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
+ if (swpo->swpo_port_no == breq->ifbr_portno)
+ return (EEXIST);
+ }
+
+ swpo = (struct switch_port *)ifs->if_switchport;
+ swpo->swpo_port_no = breq->ifbr_portno;
+
+ break;
default:
error = ENOTTY;
break;
@@ -3161,7 +3205,13 @@ swofp_action_output(struct switch_softc *sc, struct mbuf *m,
/* no support yet */
break;
case OFP_PORT_LOCAL:
- /* no support yet */
+ TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
+ if (swpo->swpo_flags & IFBIF_LOCAL) {
+ TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
+ swpo_fwdp_next);
+ break;
+ }
+ }
break;
default:
TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
@@ -5558,7 +5608,10 @@ swofp_mp_recv_port_stats(struct switch_softc *sc, struct mbuf *m)
if (ifs == NULL)
continue;
- postat.pt_port_no = htonl(swpo->swpo_port_no);
+ if (swpo->swpo_flags & IFBIF_LOCAL)
+ postat.pt_port_no = htonl(OFP_PORT_LOCAL);
+ else
+ postat.pt_port_no = htonl(swpo->swpo_port_no);
postat.pt_rx_packets = htobe64(ifs->if_ipackets);
postat.pt_tx_packets = htobe64(ifs->if_opackets);
postat.pt_rx_bytes = htobe64(ifs->if_obytes);
@@ -5888,7 +5941,10 @@ swofp_mp_recv_port_desc(struct switch_softc *sc, struct mbuf *m)
if (ifs == NULL)
continue;
- swp.swp_number = htonl(swpo->swpo_port_no);
+ if (swpo->swpo_flags & IFBIF_LOCAL)
+ swp.swp_number = htonl(OFP_PORT_LOCAL);
+ else
+ swp.swp_number = htonl(swpo->swpo_port_no);
memcpy(swp.swp_macaddr,
((struct arpcom *)ifs)->ac_enaddr, ETHER_ADDR_LEN);
diff --git a/sys/sys/sockio.h b/sys/sys/sockio.h
index 6ccf4e62b71..28202860775 100644
--- a/sys/sys/sockio.h
+++ b/sys/sys/sockio.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sockio.h,v 1.67 2016/08/28 07:22:11 reyk Exp $ */
+/* $OpenBSD: sockio.h,v 1.68 2016/09/02 10:01:36 goda Exp $ */
/* $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $ */
/*-
@@ -102,6 +102,7 @@
#define SIOCBRDGGTO _IOWR('i', 70, struct ifbrparam)/* cache timeout */
#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 SIOCBRDGARL _IOW('i', 77, struct ifbrlreq) /* add bridge rule */
#define SIOCBRDGFRL _IOW('i', 78, struct ifbrlreq) /* flush brdg rules */
@@ -122,6 +123,16 @@
#define SIOCBRDGSPROTO _IOW('i', 90, struct ifbrparam)/* set protocol */
#define SIOCBRDGS
+/* Following ioctls for switch(4) has compatibility to bridge(4) */
+#define SIOCSWSFLOWMAX SIOCBRDGSCACHE /* set max flow per table */
+#define SIOCSWGFLOWMAX SIOCBRDGGCACHE /* get max flow per table */
+
+#define SIOCSWGDPID _IOWR('i', 91, struct ifbrparam)/* set datapath id */
+#define SIOCSWSDPID _IOW('i', 91, struct ifbrparam)/* get datapath id */
+#define SIOCSWGMAXGROUP _IOWR('i', 92, struct ifbrparam)/* get max groups */
+#define SIOCSWSMAXGROUP _IOW('i', 92, struct ifbrparam)/* set max groups */
+#define SIOCSWSPORTNO _IOWR('i', 93, struct ifbreq) /* set port number */
+
#define SIOCSIFMTU _IOW('i', 127, struct ifreq) /* set ifnet mtu */
#define SIOCGIFMTU _IOWR('i', 126, struct ifreq) /* get ifnet mtu */
#define SIOCSIFASYNCMAP _IOW('i', 125, struct ifreq) /* set ppp asyncmap */