Retire switch(4) it never really was production ready and the OpenFlow
authorclaudio <claudio@openbsd.org>
Thu, 11 Nov 2021 10:03:08 +0000 (10:03 +0000)
committerclaudio <claudio@openbsd.org>
Thu, 11 Nov 2021 10:03:08 +0000 (10:03 +0000)
API implemented is a deadend.
OK akoshibe@ yasuoka@ deraadt@ kn@ patrick@ sthen@

23 files changed:
sys/arch/alpha/alpha/conf.c
sys/arch/amd64/amd64/conf.c
sys/arch/arm/arm/conf.c
sys/arch/arm64/arm64/conf.c
sys/arch/hppa/hppa/conf.c
sys/arch/i386/i386/conf.c
sys/arch/landisk/landisk/conf.c
sys/arch/loongson/loongson/conf.c
sys/arch/luna88k/luna88k/conf.c
sys/arch/macppc/macppc/conf.c
sys/arch/octeon/octeon/conf.c
sys/arch/powerpc64/powerpc64/conf.c
sys/arch/riscv64/riscv64/conf.c
sys/arch/sparc64/sparc64/conf.c
sys/conf/GENERIC
sys/conf/files
sys/net/if.c
sys/net/if_bridge.h
sys/net/if_switch.c [deleted file]
sys/net/if_switch.h [deleted file]
sys/net/switchctl.c [deleted file]
sys/net/switchofp.c [deleted file]
sys/sys/sockio.h

index d3f2667..61f25ea 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.89 2021/01/23 05:08:34 thfr Exp $  */
+/*     $OpenBSD: conf.c,v 1.90 2021/11/11 10:03:08 claudio Exp $       */
 /*     $NetBSD: conf.c,v 1.16 1996/10/18 21:26:57 cgd Exp $    */
 
 /*-
@@ -128,7 +128,6 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -205,7 +204,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 66: was USB scanners */
        cdev_fuse_init(NFUSE,fuse),     /* 67: fuse */
        cdev_tun_init(NTUN,tap),        /* 68: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 69: switch(4) control interface */
+       cdev_notdef(),                  /* 69: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 70: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 71: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 72: USB joystick/gamecontroller */
index 3005c0b..d4d95ae 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.73 2021/01/23 05:08:34 thfr Exp $  */
+/*     $OpenBSD: conf.c,v 1.74 2021/11/11 10:03:08 claudio Exp $       */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -173,7 +173,6 @@ cdev_decl(pci);
 #include "fuse.h"
 #include "pvbus.h"
 #include "ipmi.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -286,7 +285,7 @@ struct cdevsw       cdevsw[] =
        cdev_tty_init(NVIOCON,viocon),  /* 94: virtio console */
        cdev_pvbus_init(NPVBUS,pvbus),  /* 95: pvbus(4) control interface */
        cdev_ipmi_init(NIPMI,ipmi),     /* 96: ipmi */
-       cdev_switch_init(NSWITCH,switch), /* 97: switch(4) control interface */
+       cdev_notdef(),                  /* 97: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 98: FIDO/U2F security keys */
        cdev_pppx_init(NPPPX,pppac),    /* 99: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 100: USB joystick/gamecontroller */
index 2cc3dfc..a97a209 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.57 2021/03/25 04:12:00 jsg Exp $   */
+/*     $OpenBSD: conf.c,v 1.58 2021/11/11 10:03:08 claudio Exp $       */
 /*     $NetBSD: conf.c,v 1.10 2002/04/19 01:04:38 wiz Exp $    */
 
 /*
@@ -264,8 +264,6 @@ struct bdevsw bdevsw[] = {
 #define        NSPKR 0
 #endif
 
-#include "switch.h"
-
 struct cdevsw cdevsw[] = {
        cdev_cn_init(1,cn),                     /*  0: virtual console */
        cdev_ctty_init(1,ctty),                 /*  1: controlling terminal */
@@ -376,7 +374,7 @@ struct cdevsw cdevsw[] = {
        cdev_disk_init(1,diskmap),              /* 102: disk mapper */
        cdev_pppx_init(NPPPX,pppx),             /* 103: pppx */
        cdev_tun_init(NTUN,tap),                /* 104: Ethernet tap */
-       cdev_switch_init(NSWITCH,switch),       /* 105: switch(4) control interface */
+       cdev_notdef(),                          /* 105: was switch(4) */
        cdev_fido_init(NFIDO,fido),             /* 106: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),            /* 107: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),             /* 108: USB joystick/gamecontroller */
index a47ca83..543b824 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.18 2021/04/26 06:05:55 jsg Exp $   */
+/*     $OpenBSD: conf.c,v 1.19 2021/11/11 10:03:08 claudio Exp $       */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -121,7 +121,6 @@ cdev_decl(pci);
 #include "openprom.h"
 #include "gpio.h"
 #include "ipmi.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -230,7 +229,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 94 */
        cdev_notdef(),                  /* 95 */
        cdev_ipmi_init(NIPMI,ipmi),     /* 96: ipmi */
-       cdev_switch_init(NSWITCH,switch), /* 97: switch(4) control interface */
+       cdev_notdef(),                  /* 97: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 98: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 99: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 100: USB joystick/gamecontroller */
index 4d7a12b..a3cb39e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.71 2021/01/23 05:08:35 thfr Exp $  */
+/*     $OpenBSD: conf.c,v 1.72 2021/11/11 10:03:09 claudio Exp $       */
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -120,7 +120,6 @@ cdev_decl(pci);
 #include "ucom.h"
 
 #include "fuse.h"
-#include "switch.h"
 
 struct cdevsw   cdevsw[] =
 {
@@ -189,7 +188,7 @@ struct cdevsw   cdevsw[] =
        cdev_pppx_init(NPPPX,pppx),     /* 57: pppx */
        cdev_fuse_init(NFUSE,fuse),     /* 58: fuse */
        cdev_tun_init(NTUN,tap),        /* 59: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 60: switch(4) control interface */
+       cdev_notdef(),                  /* 60: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 61: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 62: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 63: USB joystick/gamecontroller */
index 788792c..f99fef7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.171 2021/01/23 05:08:35 thfr Exp $ */
+/*     $OpenBSD: conf.c,v 1.172 2021/11/11 10:03:09 claudio Exp $      */
 /*     $NetBSD: conf.c,v 1.75 1996/05/03 19:40:20 christos Exp $       */
 
 /*
@@ -173,7 +173,6 @@ cdev_decl(pci);
 #include "fuse.h"
 #include "pvbus.h"
 #include "ipmi.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -286,7 +285,7 @@ struct cdevsw       cdevsw[] =
        cdev_tun_init(NTUN,tap),        /* 94: Ethernet network tunnel */
        cdev_pvbus_init(NPVBUS,pvbus),  /* 95: pvbus(4) control interface */
        cdev_ipmi_init(NIPMI,ipmi),     /* 96: ipmi */
-       cdev_switch_init(NSWITCH,switch), /* 97: switch(4) control interface */
+       cdev_notdef(),                  /* 97: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 98: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 99: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 100: USB joystick/gamecontroller */
index 45cfbd3..1ceb054 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.43 2021/01/23 05:08:35 thfr Exp $  */
+/*     $OpenBSD: conf.c,v 1.44 2021/11/11 10:03:09 claudio Exp $       */
 
 /*
  * Copyright (c) 1994-1998 Mark Brinicombe.
@@ -243,7 +243,6 @@ struct bdevsw bdevsw[] = {
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct cdevsw cdevsw[] = {
        cdev_cn_init(1,cn),                     /*  0: virtual console */
@@ -355,7 +354,7 @@ struct cdevsw cdevsw[] = {
        cdev_pppx_init(NPPPX,pppx),             /* 102: pppx */
        cdev_fuse_init(NFUSE,fuse),             /* 103: fuse */
        cdev_tun_init(NTUN,tap),                /* 104: Ethernet network tap */
-       cdev_switch_init(NSWITCH,switch),       /* 105: switch(4) control interface */
+       cdev_notdef(),                          /* 105: was switch(4) */
        cdev_fido_init(NFIDO,fido),             /* 106: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),            /* 107: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),             /* 108: USB joystick/gamecontroller */
index 0520e67..3b939ae 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.30 2021/01/23 05:08:35 thfr Exp $ */
+/*     $OpenBSD: conf.c,v 1.31 2021/11/11 10:03:09 claudio Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -131,7 +131,6 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -214,7 +213,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 72: was USB scanners */
        cdev_fuse_init(NFUSE,fuse),     /* 73: fuse */
        cdev_tun_init(NTUN,tap),        /* 74: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 75: switch(4) control interface */
+       cdev_notdef(),                  /* 75: was switch(4) */
        cdev_notdef(),                  /* 76 */
        cdev_notdef(),                  /* 77 */
        cdev_notdef(),                  /* 78 */
index d10b67d..d496ea3 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.34 2020/07/06 04:32:25 dlg Exp $   */
+/*     $OpenBSD: conf.c,v 1.35 2021/11/11 10:03:09 claudio Exp $       */
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -73,7 +73,6 @@
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct bdevsw  bdevsw[] =
 {
@@ -160,7 +159,7 @@ struct cdevsw       cdevsw[] =
        cdev_disk_init(1,diskmap),      /* 54: disk mapper */
        cdev_pppx_init(NPPPX,pppx),     /* 55: pppx */
        cdev_tun_init(NTUN,tap),        /* 56: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 57: switch(4) control interface */
+       cdev_notdef(),                  /* 57: was switch(4) */
        cdev_pppx_init(NPPPX,pppac),    /* 58: PPP Access Concentrator */
 };
 int    nchrdev = nitems(cdevsw);
index 6a67a39..e28e9cc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.73 2021/01/23 05:08:35 thfr Exp $ */
+/*     $OpenBSD: conf.c,v 1.74 2021/11/11 10:03:09 claudio Exp $ */
 
 /*
  * Copyright (c) 1997 Per Fogelstrom
@@ -129,7 +129,6 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct cdevsw cdevsw[] = {
        cdev_cn_init(1,cn),             /* 0: virtual console */
@@ -229,7 +228,7 @@ struct cdevsw cdevsw[] = {
        cdev_tun_init(NTUN,tap),        /* 86: Ethernet network tunnel */
        cdev_drm_init(NDRM,drm),        /* 87: drm */
        cdev_fuse_init(NFUSE,fuse),     /* 88: fuse */
-       cdev_switch_init(NSWITCH,switch), /* 89: switch(4) control interface */
+       cdev_notdef(),                  /* 89: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 90: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 91: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 92: USB joystick/gamecontroller */
index b8a40b0..d3dc9d1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.26 2021/01/23 05:08:36 thfr Exp $ */
+/*     $OpenBSD: conf.c,v 1.27 2021/11/11 10:03:09 claudio Exp $ */
 
 /*
  * Copyright (c) 1992, 1993
@@ -146,7 +146,6 @@ cdev_decl(pci);
 #include "fuse.h"
 #include "octboot.h"
 #include "openprom.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -233,7 +232,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 72: was USB scanners */
        cdev_notdef(),                  /* 73: fuse on other mips64 */
        cdev_tun_init(NTUN,tap),        /* 74: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 75: switch(4) control interface */
+       cdev_notdef(),                  /* 75: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 76: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 77: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 78: USB joystick/gamecontroller */
index 7d2a989..bda9235 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.12 2021/10/05 04:55:53 deraadt Exp $       */
+/*     $OpenBSD: conf.c,v 1.13 2021/11/11 10:03:09 claudio Exp $       */
 
 /*-
  * Copyright (c) 1991 The Regents of the University of California.
@@ -86,7 +86,6 @@ cdev_decl(lpt);
 #include "pty.h"
 #include "radio.h"
 #include "st.h"
-#include "switch.h"
 #include "tun.h"
 #include "ucom.h"
 #include "ugen.h"
@@ -184,7 +183,7 @@ struct cdevsw cdevsw[] =
        cdev_notdef(),                  /* 71 */
        cdev_pppx_init(NPPPX,pppx),     /* 72: pppx */
        cdev_pppx_init(NPPPX,pppac),    /* 73: PPP Access Concentrator */
-       cdev_switch_init(NSWITCH,switch), /* 74: switch(4) control interface */
+       cdev_notdef(),                  /* 74: was switch(4) */
        cdev_tun_init(NTUN,tap),        /* 75: Ethernet network tunnel */
        cdev_tun_init(NTUN,tun),        /* 76: network tunnel */
        cdev_notdef(),                  /* 77 */
index bdebadc..27618a6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.11 2021/10/05 18:32:28 deraadt Exp $       */
+/*     $OpenBSD: conf.c,v 1.12 2021/11/11 10:03:09 claudio Exp $       */
 
 /*
  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
@@ -110,7 +110,6 @@ cdev_decl(pci);
 #include "fuse.h"
 #include "openprom.h"
 #include "ipmi.h"
-#include "switch.h"
 
 struct cdevsw  cdevsw[] =
 {
@@ -219,7 +218,7 @@ struct cdevsw       cdevsw[] =
        cdev_notdef(),                  /* 94 */
        cdev_notdef(),                  /* 95 */
        cdev_ipmi_init(NIPMI,ipmi),     /* 96: ipmi */
-       cdev_switch_init(NSWITCH,switch), /* 97: switch(4) control interface */
+       cdev_notdef(),                  /* 97: was switch(4) */
        cdev_notdef(),                  /* 98: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 99: PPP Access Concentrator */
        cdev_notdef(),                  /* 100: USB joystick/gamecontroller */
index 6e7df92..9c5b692 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: conf.c,v 1.85 2021/01/23 05:08:36 thfr Exp $  */
+/*     $OpenBSD: conf.c,v 1.86 2021/11/11 10:03:09 claudio Exp $       */
 /*     $NetBSD: conf.c,v 1.17 2001/03/26 12:33:26 lukem Exp $ */
 
 /*
@@ -119,7 +119,6 @@ cdev_decl(pci);
 #include "vscsi.h"
 #include "pppx.h"
 #include "fuse.h"
-#include "switch.h"
 
 struct bdevsw  bdevsw[] =
 {
@@ -295,7 +294,7 @@ struct cdevsw       cdevsw[] =
        cdev_vdsp_init(NVDSP,vdsp),     /* 133: vdsp */
        cdev_fuse_init(NFUSE,fuse),     /* 134: fuse */
        cdev_tun_init(NTUN,tap),        /* 135: Ethernet network tunnel */
-       cdev_switch_init(NSWITCH,switch), /* 136: switch(4) control interface */
+       cdev_notdef(),                  /* 136: was switch(4) */
        cdev_fido_init(NFIDO,fido),     /* 137: FIDO/U2F security key */
        cdev_pppx_init(NPPPX,pppac),    /* 138: PPP Access Concentrator */
        cdev_ujoy_init(NUJOY,ujoy),     /* 139: USB joystick/gamecontroller */
index 71db305..33326a3 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.279 2021/09/22 18:24:04 benno Exp $
+#      $OpenBSD: GENERIC,v 1.280 2021/11/11 10:03:10 claudio Exp $
 #
 #      Machine-independent option; used by all architectures for their
 #      GENERIC kernel
@@ -108,7 +108,6 @@ pseudo-device       tun             # network tunneling over tty (tun & tap)
 pseudo-device  vether          # Virtual ethernet
 pseudo-device  vxlan           # Virtual extensible LAN
 pseudo-device  vlan            # IEEE 802.1Q VLAN
-pseudo-device  switch          # Switch
 pseudo-device  wg              # WireGuard
 
 pseudo-device  bio     1       # ioctl multiplexing device
index b69d1d7..b33c844 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files,v 1.705 2021/11/08 14:52:08 stsp Exp $
+#      $OpenBSD: files,v 1.706 2021/11/11 10:03:10 claudio Exp $
 #      $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
@@ -577,7 +577,6 @@ pseudo-device bpe: ifnet, ether, ifmedia, etherbridge
 pseudo-device vether: ifnet, ether
 pseudo-device pppx: ifnet
 pseudo-device vxlan: ifnet, ether, ifmedia
-pseudo-device switch: ifnet, ether
 pseudo-device wg: ifnet
 
 pseudo-device ksyms
@@ -822,9 +821,6 @@ file net/bridgestp.c                        bridge
 file net/if_etherbridge.c              etherbridge
 file net/if_veb.c                      veb
 file net/if_vlan.c                     vlan                    needs-count
-file net/if_switch.c                   switch                  needs-count
-file net/switchctl.c                   switch
-file net/switchofp.c                   switch
 file net/pipex.c                       pipex
 file net/radix.c                       pf | ipsec | pipex | nfsserver
 file net/rtable.c
index 8fe99ef..2e9a968 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if.c,v 1.643 2021/07/20 16:32:28 bluhm Exp $  */
+/*     $OpenBSD: if.c,v 1.644 2021/11/11 10:03:10 claudio Exp $        */
 /*     $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $  */
 
 /*
@@ -68,7 +68,6 @@
 #include "pf.h"
 #include "pfsync.h"
 #include "ppp.h"
-#include "switch.h"
 #include "if_wg.h"
 
 #include <sys/param.h>
@@ -911,13 +910,6 @@ if_netisr(void *unused)
 #if NBRIDGE > 0
                if (n & (1 << NETISR_BRIDGE))
                        bridgeintr();
-#endif
-#if NSWITCH > 0
-               if (n & (1 << NETISR_SWITCH)) {
-                       KERNEL_LOCK();
-                       switchintr();
-                       KERNEL_UNLOCK();
-               }
 #endif
                t |= n;
        }
@@ -2260,7 +2252,6 @@ forceup:
        case SIOCBRDGSIFCOST:
        case SIOCBRDGSTXHC:
        case SIOCBRDGSPROTO:
-       case SIOCSWSPORTNO:
 #endif
                if ((error = suser(p)) != 0)
                        break;
index ed384be..6fa74c8 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_bridge.h,v 1.72 2021/03/10 10:21:47 jsg Exp $      */
+/*     $OpenBSD: if_bridge.h,v 1.73 2021/11/11 10:03:10 claudio Exp $  */
 
 /*
  * Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -155,8 +155,6 @@ 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
@@ -167,9 +165,6 @@ 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
diff --git a/sys/net/if_switch.c b/sys/net/if_switch.c
deleted file mode 100644 (file)
index 43449a7..0000000
+++ /dev/null
@@ -1,1589 +0,0 @@
-/*     $OpenBSD: if_switch.c,v 1.44 2021/07/07 20:19:01 sashan Exp $   */
-
-/*
- * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
- * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "bpfilter.h"
-#include "pf.h"
-#include "vlan.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/queue.h>
-#include <sys/selinfo.h>
-#include <sys/pool.h>
-#include <sys/syslog.h>
-
-#include <net/if_types.h>
-#include <net/netisr.h>
-#include <net/if.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <net/ethertypes.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/icmp6.h>
-#include <netinet6/nd6.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#include <netinet/ip_icmp.h>
-
-#if NPF > 0
-#include <net/pfvar.h>
-#endif
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
-#include <net/ofp.h>
-#include <net/if_bridge.h>
-#include <net/if_switch.h>
-
-int     switch_clone_create(struct if_clone *, int);
-int     switch_clone_destroy(struct ifnet *);
-void    switch_process(struct ifnet *, struct mbuf *);
-int     switch_port_set_local(struct switch_softc *, struct switch_port *);
-int     switch_port_unset_local(struct switch_softc *, struct switch_port *);
-int     switch_ioctl(struct ifnet *, unsigned long, caddr_t);
-int     switch_port_add(struct switch_softc *, struct ifbreq *);
-void    switch_port_detach(void *);
-int     switch_port_del(struct switch_softc *, struct ifbreq *);
-int     switch_port_list(struct switch_softc *, struct ifbifconf *);
-struct mbuf *
-        switch_input(struct ifnet *, struct mbuf *, uint64_t, void *);
-struct mbuf
-       *switch_port_ingress(struct switch_softc *, struct ifnet *,
-           struct mbuf *);
-int     switch_ifenqueue(struct switch_softc *, struct ifnet *,
-           struct mbuf *, int);
-void    switch_port_ifb_start(struct ifnet *);
-
-struct mbuf
-       *switch_flow_classifier_udp(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_tcp(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_icmpv4(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_nd6(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_icmpv6(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_ipv4(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_ipv6(struct mbuf *, int *,
-           struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier_arp(struct mbuf *, int *,
-           struct switch_flow_classify *);
-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 *);
-void    switch_flow_classifier_dump(struct switch_softc *,
-           struct switch_flow_classify *);
-void    switchattach(int);
-void   switch_take(void *);
-void   switch_rele(void *);
-
-struct if_clone switch_cloner =
-    IF_CLONE_INITIALIZER("switch", switch_clone_create, switch_clone_destroy);
-
-LIST_HEAD(, switch_softc) switch_list;
-struct niqueue switchintrq = NIQUEUE_INITIALIZER(1024, NETISR_SWITCH);
-struct rwlock switch_ifs_lk = RWLOCK_INITIALIZER("switchifs");
-
-struct pool swfcl_pool;
-
-const struct ether_brport switch_brport = {
-       switch_input,
-       switch_take,
-       switch_rele,
-       NULL,
-};
-
-void
-switchattach(int n)
-{
-       pool_init(&swfcl_pool, sizeof(union switch_field), 0, 0, 0,
-           "swfcl", NULL);
-       swofp_attach();
-       LIST_INIT(&switch_list);
-       if_clone_attach(&switch_cloner);
-}
-
-struct switch_softc *
-switch_lookup(int unit)
-{
-       struct switch_softc     *sc;
-
-       /* must hold switch_ifs_lk */
-       LIST_FOREACH(sc, &switch_list, sc_switch_next) {
-               if (sc->sc_unit == unit)
-                       return (sc);
-       }
-
-       return (NULL);
-}
-
-int
-switch_clone_create(struct if_clone *ifc, int unit)
-{
-       struct switch_softc     *sc;
-       struct ifnet            *ifp;
-
-       sc = malloc(sizeof(struct switch_softc), M_DEVBUF, M_WAITOK|M_ZERO);
-       ifp = &sc->sc_if;
-       snprintf(ifp->if_xname, sizeof ifp->if_xname, "switch%d", unit);
-       ifp->if_softc = sc;
-       ifp->if_mtu = ETHERMTU;
-       ifp->if_ioctl = switch_ioctl;
-       ifp->if_output = NULL;
-       ifp->if_start = NULL;
-       ifp->if_type = IFT_BRIDGE;
-       ifp->if_hdrlen = ETHER_HDR_LEN;
-       ifp->if_xflags = IFXF_CLONED;
-       TAILQ_INIT(&sc->sc_swpo_list);
-
-       sc->sc_unit = unit;
-       sc->sc_stp = bstp_create();
-       if (!sc->sc_stp) {
-               free(sc, M_DEVBUF, sizeof(*sc));
-               return (ENOMEM);
-       }
-
-       if_attach(ifp);
-       if_alloc_sadl(ifp);
-
-#if NBPFILTER > 0
-       bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN);
-#endif
-
-       swofp_create(sc);
-
-       LIST_INSERT_HEAD(&switch_list, sc, sc_switch_next);
-
-       return (0);
-}
-
-int
-switch_clone_destroy(struct ifnet *ifp)
-{
-       struct switch_softc     *sc = ifp->if_softc;
-       struct switch_port      *swpo, *tp;
-       struct ifnet            *ifs;
-
-       NET_LOCK();
-       TAILQ_FOREACH_SAFE(swpo, &sc->sc_swpo_list, swpo_list_next, tp) {
-               if ((ifs = if_get(swpo->swpo_ifindex)) != NULL) {
-                       switch_port_detach(ifs);
-                       if_put(ifs);
-               } else
-                       log(LOG_ERR, "failed to cleanup on ifindex(%d)\n",
-                           swpo->swpo_ifindex);
-       }
-       NET_UNLOCK();
-       LIST_REMOVE(sc, sc_switch_next);
-       bstp_destroy(sc->sc_stp);
-       swofp_destroy(sc);
-       switch_dev_destroy(sc);
-       if_detach(ifp);
-       free(sc, M_DEVBUF, sizeof(*sc));
-
-       return (0);
-}
-
-
-void
-switchintr(void)
-{
-       struct mbuf_list         ml;
-       struct mbuf             *m;
-       struct ifnet            *ifp;
-
-       niq_delist(&switchintrq, &ml);
-       if (ml_empty(&ml))
-               return;
-
-       while ((m = ml_dequeue(&ml)) != NULL) {
-               KASSERT(m->m_flags & M_PKTHDR);
-               ifp = if_get(m->m_pkthdr.ph_ifidx);
-               if (ifp == NULL) {
-                       m_freem(m);
-                       continue;
-               }
-               switch_process(ifp, m);
-               if_put(ifp);
-       }
-
-}
-
-void
-switch_process(struct ifnet *ifp, struct mbuf *m)
-{
-       struct switch_softc             *sc = NULL;
-       struct switch_port              *swpo;
-       struct switch_flow_classify      swfcl = { 0 };
-
-       swpo = (struct switch_port *)ifp->if_switchport;
-       if (swpo == NULL)
-               goto discard;
-       sc = swpo->swpo_switch;
-       if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
-               goto discard;
-
-#if NBPFILTER > 0
-       if (sc->sc_if.if_bpf)
-               bpf_mtap_ether(sc->sc_if.if_bpf, m, BPF_DIRECTION_IN);
-#endif
-
-       if (m->m_pkthdr.len < sizeof(struct ether_header))
-               goto discard;
-
-       if ((m = switch_port_ingress(sc, ifp, m)) == NULL)
-               return; /* m was freed in switch_process_ingress */
-
-       if ((m = switch_flow_classifier(m, swpo->swpo_port_no,
-           &swfcl)) == NULL) {
-               switch_swfcl_free(&swfcl);
-               return;  /* m was freed in switch_flow_classifier */
-       }
-
-       if (sc->sc_if.if_flags & IFF_DEBUG)
-               switch_flow_classifier_dump(sc, &swfcl);
-
-       if (!sc->switch_process_forward)
-               goto discard;
-
-       (sc->switch_process_forward)(sc, &swfcl, m);
-
-       switch_swfcl_free(&swfcl);
-       return;
-
-discard:
-       m_freem(m);
-       switch_swfcl_free(&swfcl);
-       if (sc)
-               sc->sc_if.if_oerrors++;
-}
-
-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;
-       struct ifbropreq        *brop = (struct ifbropreq *)data;
-       struct ifbrlconf        *bc = (struct ifbrlconf *)data;
-       struct ifbreq           *breq = (struct ifbreq *)data;
-       struct switch_softc     *sc = ifp->if_softc;
-       struct bstp_state       *bs = sc->sc_stp;
-       struct bstp_port        *bp;
-       struct ifnet            *ifs;
-       struct switch_port      *swpo;
-       int                      error = 0;
-
-       switch (cmd) {
-       case SIOCBRDGADD:
-               if ((error = suser(curproc)) != 0)
-                       break;
-               error = switch_port_add(sc, (struct ifbreq *)data);
-               break;
-       case SIOCBRDGDEL:
-               if ((error = suser(curproc)) != 0)
-                       break;
-               error = switch_port_del(sc, (struct ifbreq *)data);
-               break;
-       case SIOCBRDGIFS:
-               error = switch_port_list(sc, (struct ifbifconf *)data);
-               break;
-       case SIOCBRDGADDL:
-               if ((error = suser(curproc)) != 0)
-                       break;
-               error = switch_port_add(sc, (struct ifbreq *)data);
-               if (error && error != EEXIST)
-                       break;
-               ifs = if_unit(breq->ifbr_ifsname);
-               if (ifs == NULL) {
-                       error = ENOENT;
-                       break;
-               }
-               swpo = (struct switch_port *)ifs->if_switchport;
-               if_put(ifs);
-               if (swpo == NULL || swpo->swpo_switch != sc) {
-                       error = ESRCH;
-                       break;
-               }
-               error = switch_port_set_local(sc, swpo);
-               break;
-       case SIOCBRDGGIFFLGS:
-               ifs = if_unit(breq->ifbr_ifsname);
-               if (ifs == NULL) {
-                       error = ENOENT;
-                       break;
-               }
-               swpo = (struct switch_port *)ifs->if_switchport;
-               if_put(ifs);
-               if (swpo == NULL || swpo->swpo_switch != sc) {
-                       error = ESRCH;
-                       break;
-               }
-               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) {
-                       if ((ifp->if_flags & IFF_RUNNING) == 0) {
-                               ifp->if_flags |= IFF_RUNNING;
-                               bstp_enable(sc->sc_stp, ifp->if_index);
-                       }
-               }
-
-               if ((ifp->if_flags & IFF_UP) == 0) {
-                       if ((ifp->if_flags & IFF_RUNNING) == IFF_RUNNING) {
-                               ifp->if_flags &= ~IFF_RUNNING;
-                               bstp_disable(sc->sc_stp);
-                       }
-               }
-
-               break;
-       case SIOCBRDGRTS:
-               baconf->ifbac_len = 0;
-               break;
-       case SIOCBRDGGRL:
-               bc->ifbrl_len = 0;
-               break;
-       case SIOCBRDGGPARAM:
-               if ((bp = bs->bs_root_port) == NULL)
-                       brop->ifbop_root_port = 0;
-               else
-                       brop->ifbop_root_port = bp->bp_ifindex;
-               brop->ifbop_maxage = bs->bs_bridge_max_age >> 8;
-               brop->ifbop_hellotime = bs->bs_bridge_htime >> 8;
-               brop->ifbop_fwddelay = bs->bs_bridge_fdelay >> 8;
-               brop->ifbop_holdcount = bs->bs_txholdcount;
-               brop->ifbop_priority = bs->bs_bridge_priority;
-               brop->ifbop_protocol = bs->bs_protover;
-               brop->ifbop_root_bridge = bs->bs_root_pv.pv_root_id;
-               brop->ifbop_root_path_cost = bs->bs_root_pv.pv_cost;
-               brop->ifbop_root_port = bs->bs_root_pv.pv_port_id;
-               brop->ifbop_desg_bridge = bs->bs_root_pv.pv_dbridge_id;
-               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 = if_unit(breq->ifbr_ifsname);
-               if (ifs == NULL) {
-                       error = ENOENT;
-                       break;
-               }
-               swpo = (struct switch_port *)ifs->if_switchport;
-               if_put(ifs);
-               if (swpo == NULL || swpo->swpo_switch != sc) {
-                       error = ESRCH;
-                       break;
-               }
-               swpo->swpo_protected = breq->ifbr_protected;
-               break;
-       case SIOCSWGDPID:
-       case SIOCSWSDPID:
-       case SIOCSWGMAXFLOW:
-       case SIOCSWGMAXGROUP:
-       case SIOCSWSPORTNO:
-               error = swofp_ioctl(ifp, cmd, data);
-               break;
-       default:
-               error = ENOTTY;
-               break;
-       }
-
-       return (error);
-}
-
-int
-switch_port_add(struct switch_softc *sc, struct ifbreq *req)
-{
-       struct ifnet            *ifs;
-       struct switch_port      *swpo;
-       int                      error;
-
-       if ((ifs = if_unit(req->ifbr_ifsname)) == NULL)
-               return (ENOENT);
-
-       if (ifs->if_type != IFT_ETHER) {
-               error = EPROTONOSUPPORT;
-               goto put;
-       }
-
-       if (ifs->if_switchport != NULL) {
-               swpo = (struct switch_port *)ifs->if_switchport;
-               if (swpo->swpo_switch == sc)
-                       error = EEXIST;
-               else
-                       error = EBUSY;
-
-               goto put;
-       }
-
-       if ((error = ifpromisc(ifs, 1)) != 0)
-               goto put;
-
-       if ((error = ether_brport_isset(ifs)) != 0)
-               goto unset;
-
-       swpo = malloc(sizeof(*swpo), M_DEVBUF, M_NOWAIT|M_ZERO);
-       if (swpo == NULL) {
-               error = ENOMEM;
-               goto unset;
-       }
-
-       swpo->swpo_switch = sc;
-       swpo->swpo_ifindex = ifs->if_index;
-       ifs->if_switchport = (caddr_t)swpo;
-       ether_brport_set(ifs, &switch_brport);
-       swpo->swpo_port_no = swofp_assign_portno(sc, ifs->if_index);
-       task_set(&swpo->swpo_dtask, switch_port_detach, ifs);
-       if_detachhook_add(ifs, &swpo->swpo_dtask);
-       if_put(ifs);
-
-       nanouptime(&swpo->swpo_appended);
-
-       TAILQ_INSERT_TAIL(&sc->sc_swpo_list, swpo, swpo_list_next);
-
-       return (0);
-
-unset:
-       ifpromisc(ifs, 0);
-put:
-
-       if_put(ifs);
-       return (error);
-}
-
-int
-switch_port_list(struct switch_softc *sc, struct ifbifconf *bifc)
-{
-       struct switch_port      *swpo;
-       struct ifnet            *ifs;
-       struct ifbreq            breq;
-       int                      total = 0, n = 0, error = 0;
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next)
-               total++;
-
-       if (bifc->ifbic_len == 0) {
-               n = total;
-               goto done;
-       }
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-               memset(&breq, 0, sizeof(breq));
-
-               if (bifc->ifbic_len < sizeof(breq))
-                       break;
-
-               ifs = if_get(swpo->swpo_ifindex);
-               if (ifs == NULL) {
-                       error = ENOENT;
-                       goto done;
-               }
-               strlcpy(breq.ifbr_ifsname, ifs->if_xname, IFNAMSIZ);
-               if_put(ifs);
-
-               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;
-
-               bifc->ifbic_len -= sizeof(breq);
-               n++;
-       }
-
-done:
-       bifc->ifbic_len = n * sizeof(breq);
-       return (error);
-}
-
-void
-switch_port_detach(void *arg)
-{
-       struct ifnet            *ifp = (struct ifnet *)arg;
-       struct switch_softc     *sc;
-       struct switch_port      *swpo;
-
-       swpo = (struct switch_port *)ifp->if_switchport;
-       sc = swpo->swpo_switch;
-       if (swpo->swpo_flags & IFBIF_LOCAL)
-               switch_port_unset_local(sc, swpo);
-
-       ifp->if_switchport = NULL;
-       if_detachhook_del(ifp, &swpo->swpo_dtask);
-       ifpromisc(ifp, 0);
-       ether_brport_clr(ifp);
-       TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
-       free(swpo, M_DEVBUF, sizeof(*swpo));
-}
-
-int
-switch_port_del(struct switch_softc *sc, struct ifbreq *req)
-{
-       struct switch_port      *swpo;
-       struct ifnet            *ifs;
-       int                      error = 0;
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-               if ((ifs = if_get(swpo->swpo_ifindex)) == NULL)
-                       continue;
-               if (strncmp(ifs->if_xname, req->ifbr_ifsname, IFNAMSIZ) == 0)
-                       break;
-               if_put(ifs);
-       }
-
-       if (swpo) {
-               switch_port_detach(ifs);
-               if_put(ifs);
-               error = 0;
-       } else
-               error = ENOENT;
-
-       return (error);
-}
-
-struct mbuf *
-switch_input(struct ifnet *ifp, struct mbuf *m, uint64_t dst, void *null)
-{
-       KASSERT(m->m_flags & M_PKTHDR);
-
-       if (m->m_flags & M_PROTO1) {
-               m->m_flags &= ~M_PROTO1;
-               return (m);
-       }
-
-       niq_enqueue(&switchintrq, m);
-
-       return (NULL);
-}
-
-
-struct mbuf *
-switch_port_ingress(struct switch_softc *sc, struct ifnet *src_if,
-    struct mbuf *m)
-{
-       struct ether_header      eh;
-
-       sc->sc_if.if_ipackets++;
-       sc->sc_if.if_ibytes += m->m_pkthdr.len;
-
-       m_copydata(m, 0, ETHER_HDR_LEN, &eh);
-#if 0
-       /* It's the "#if 0" because it doesn't test switch(4) with pf(4)
-        * or with ipsec(4).
-        */
-       if ((m = bridge_ip((struct bridge_softc *)sc,
-           PF_IN, src_if, &eh, m)) == NULL) {
-               sc->sc_if.if_ierrors++;
-               return (NULL);
-       }
-#endif /* NPF */
-
-       return (m);
-}
-
-void
-switch_port_egress(struct switch_softc *sc, struct switch_fwdp_queue *fwdp_q,
-    struct mbuf *m)
-{
-       struct switch_port      *swpo;
-       struct ifnet            *dst_if;
-       struct mbuf             *mc;
-       struct ether_header      eh;
-       int                      len, used = 0;
-
-#if NBPFILTER > 0
-       if (sc->sc_if.if_bpf)
-               bpf_mtap(sc->sc_if.if_bpf, m, BPF_DIRECTION_OUT);
-#endif
-
-       m_copydata(m, 0, ETHER_HDR_LEN, &eh);
-       TAILQ_FOREACH(swpo, fwdp_q, swpo_fwdp_next) {
-
-               if ((dst_if = if_get(swpo->swpo_ifindex)) == NULL)
-                       continue;
-
-               if ((dst_if->if_flags & IFF_RUNNING) == 0)
-                       goto out;
-
-               if (TAILQ_NEXT(swpo, swpo_fwdp_next) == NULL) {
-                       mc = m;
-                       used = 1;
-               } else {
-                       mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT);
-                       if (mc == NULL)
-                               goto out;
-               }
-
-#if 0
-               /* It's the "#if 0" because it doesn't test switch(4) with pf(4)
-                * or with ipsec(4).
-                */
-               if ((mc = bridge_ip((struct bridge_softc *)sc,
-                   PF_OUT, dst_if, &eh, mc)) == NULL) {
-                       sc->sc_if.if_ierrors++;
-                       goto out;
-               }
-#endif
-
-               len = mc->m_pkthdr.len;
-#if NVLAN > 0
-               if ((mc->m_flags & M_VLANTAG) &&
-                   (dst_if->if_capabilities & IFCAP_VLAN_HWTAGGING) == 0)
-                       len += ETHER_VLAN_ENCAP_LEN;
-#endif
-
-               /*
-                * 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(&sc->sc_if, dst_if, &eh, mc);
-               else
-                       switch_ifenqueue(sc, dst_if, mc,
-                           (swpo->swpo_flags & IFBIF_LOCAL));
- out:
-
-               if_put(dst_if);
-       }
-
-       if (!used)
-               m_freem(m);
-}
-
-int
-switch_ifenqueue(struct switch_softc *sc, struct ifnet *ifp,
-    struct mbuf *m, int local)
-{
-       struct mbuf_list         ml = MBUF_LIST_INITIALIZER();
-       int                      error, len;
-
-       /* Loop prevention. */
-       m->m_flags |= M_PROTO1;
-
-       KASSERT(m->m_flags & M_PKTHDR);
-       len = m->m_pkthdr.len;
-
-       if (local) {
-               ml_enqueue(&ml, m);
-               if_input(ifp, &ml);
-       } else {
-               error = if_enqueue(ifp, m);
-               if (error) {
-                       sc->sc_if.if_oerrors++;
-                       return (error);
-               }
-               sc->sc_if.if_opackets++;
-               sc->sc_if.if_obytes += len;
-       }
-
-       return (0);
-}
-
-void
-switch_port_ifb_start(struct ifnet *ifp)
-{
-       struct mbuf             *m;
-       struct mbuf_list         ml = MBUF_LIST_INITIALIZER();
-
-       for (;;) {
-               m = ifq_dequeue(&ifp->if_snd);
-               if (m == NULL)
-                       return;
-
-#if NBPFILTER > 0
-               if (ifp->if_bpf)
-                       bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
-#endif /* NBPFILTER > 0 */
-
-               ml_enqueue(&ml, m);
-               if_input(ifp, &ml);
-       }
-}
-
-/*
- * Flow Classifier
- */
-
-int
-switch_swfcl_dup(struct switch_flow_classify *from,
-    struct switch_flow_classify *to)
-{
-       memset(to, 0, sizeof(*to));
-
-       to->swfcl_flow_hash = from->swfcl_flow_hash;
-       to->swfcl_metadata = from->swfcl_metadata;
-       to->swfcl_cookie = from->swfcl_cookie;
-       to->swfcl_table_id = from->swfcl_table_id;
-       to->swfcl_in_port = from->swfcl_in_port;
-
-       if (from->swfcl_tunnel) {
-               to->swfcl_tunnel = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_tunnel == NULL)
-                       goto failed;
-               memcpy(to->swfcl_tunnel, from->swfcl_tunnel,
-                   sizeof(*from->swfcl_tunnel));
-       }
-       if (from->swfcl_ether) {
-               to->swfcl_ether = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_ether == NULL)
-                       goto failed;
-               memcpy(to->swfcl_ether, from->swfcl_ether,
-                   sizeof(*from->swfcl_ether));
-       }
-       if (from->swfcl_vlan) {
-               to->swfcl_vlan = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_vlan == NULL)
-                       goto failed;
-               memcpy(to->swfcl_vlan, from->swfcl_vlan,
-                   sizeof(*from->swfcl_vlan));
-       }
-       if (from->swfcl_ipv4) {
-               to->swfcl_ipv4 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_ipv4 == NULL)
-                       goto failed;
-               memcpy(to->swfcl_ipv4, from->swfcl_ipv4,
-                   sizeof(*from->swfcl_ipv4));
-       }
-       if (from->swfcl_ipv6) {
-               to->swfcl_ipv6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_ipv6 == NULL)
-                       goto failed;
-               memcpy(to->swfcl_ipv6, from->swfcl_ipv6,
-                   sizeof(*from->swfcl_ipv6));
-       }
-       if (from->swfcl_arp) {
-               to->swfcl_arp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_arp == NULL)
-                       goto failed;
-               memcpy(to->swfcl_arp, from->swfcl_arp,
-                   sizeof(*from->swfcl_arp));
-
-       }
-       if (from->swfcl_nd6) {
-               to->swfcl_nd6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_nd6 == NULL)
-                       goto failed;
-               memcpy(to->swfcl_nd6, from->swfcl_nd6,
-                   sizeof(*from->swfcl_nd6));
-       }
-       if (from->swfcl_icmpv4) {
-               to->swfcl_icmpv4 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_icmpv4 == NULL)
-                       goto failed;
-               memcpy(to->swfcl_icmpv4, from->swfcl_icmpv4,
-                   sizeof(*from->swfcl_icmpv4));
-       }
-       if (from->swfcl_icmpv6) {
-               to->swfcl_icmpv6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_icmpv6 == NULL)
-                       goto failed;
-               memcpy(to->swfcl_icmpv6, from->swfcl_icmpv6,
-                   sizeof(*from->swfcl_icmpv6));
-       }
-       if (from->swfcl_tcp) {
-               to->swfcl_tcp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_tcp == NULL)
-                       goto failed;
-               memcpy(to->swfcl_tcp, from->swfcl_tcp,
-                   sizeof(*from->swfcl_tcp));
-       }
-       if (from->swfcl_udp) {
-               to->swfcl_udp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_udp == NULL)
-                       goto failed;
-               memcpy(to->swfcl_udp, from->swfcl_udp,
-                   sizeof(*from->swfcl_udp));
-       }
-       if (from->swfcl_sctp) {
-               to->swfcl_sctp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (to->swfcl_sctp == NULL)
-                       goto failed;
-               memcpy(to->swfcl_sctp, from->swfcl_sctp,
-                   sizeof(*from->swfcl_sctp));
-       }
-
-       return (0);
- failed:
-       switch_swfcl_free(to);
-       return (ENOBUFS);
-}
-
-void
-switch_swfcl_free(struct switch_flow_classify *swfcl)
-{
-       if (swfcl->swfcl_tunnel)
-               pool_put(&swfcl_pool, swfcl->swfcl_tunnel);
-       if (swfcl->swfcl_ether)
-               pool_put(&swfcl_pool, swfcl->swfcl_ether);
-       if (swfcl->swfcl_vlan)
-               pool_put(&swfcl_pool, swfcl->swfcl_vlan);
-       if (swfcl->swfcl_ipv4)
-               pool_put(&swfcl_pool, swfcl->swfcl_ipv4);
-       if (swfcl->swfcl_ipv6)
-               pool_put(&swfcl_pool, swfcl->swfcl_ipv6);
-       if (swfcl->swfcl_arp)
-               pool_put(&swfcl_pool, swfcl->swfcl_arp);
-       if (swfcl->swfcl_nd6)
-               pool_put(&swfcl_pool, swfcl->swfcl_nd6);
-       if (swfcl->swfcl_icmpv4)
-               pool_put(&swfcl_pool, swfcl->swfcl_icmpv4);
-       if (swfcl->swfcl_icmpv6)
-               pool_put(&swfcl_pool, swfcl->swfcl_icmpv6);
-       if (swfcl->swfcl_tcp)
-               pool_put(&swfcl_pool, swfcl->swfcl_tcp);
-       if (swfcl->swfcl_udp)
-               pool_put(&swfcl_pool, swfcl->swfcl_udp);
-       if (swfcl->swfcl_sctp)
-               pool_put(&swfcl_pool, swfcl->swfcl_sctp);
-
-       memset(swfcl, 0, sizeof(*swfcl));
-}
-
-struct mbuf *
-switch_flow_classifier_udp(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct udphdr   *uh;
-
-       swfcl->swfcl_udp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_udp == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + sizeof(*uh)) &&
-           (m = m_pullup(m, *offset + sizeof(*uh))) == NULL)
-               return (NULL);
-
-       uh = (struct udphdr *)((m)->m_data + *offset);
-
-       swfcl->swfcl_udp->udp_src = uh->uh_sport;
-       swfcl->swfcl_udp->udp_dst = uh->uh_dport;
-
-       return (m);
-}
-
-struct mbuf *
-switch_flow_classifier_tcp(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct tcphdr   *th;
-
-       swfcl->swfcl_tcp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_tcp == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + sizeof(*th)) &&
-           (m = m_pullup(m, *offset + sizeof(*th))) == NULL)
-               return (NULL);
-
-       th = (struct tcphdr *)((m)->m_data + *offset);
-
-       swfcl->swfcl_tcp->tcp_src = th->th_sport;
-       swfcl->swfcl_tcp->tcp_dst = th->th_dport;
-       swfcl->swfcl_tcp->tcp_flags = th->th_flags;
-
-       return (m);
-}
-
-struct mbuf *
-switch_flow_classifier_icmpv4(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct icmp     *icmp;
-
-       swfcl->swfcl_icmpv4 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_icmpv4 == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + ICMP_MINLEN) &&
-           (m = m_pullup(m, (*offset + ICMP_MINLEN))) == NULL)
-               return (NULL);
-
-       icmp = (struct icmp *)((m)->m_data + *offset);
-
-       swfcl->swfcl_icmpv4->icmpv4_type = icmp->icmp_type;
-       swfcl->swfcl_icmpv4->icmpv4_code = icmp->icmp_code;
-
-       return (m);
-}
-
-#ifdef INET6
-struct mbuf *
-switch_flow_classifier_nd6(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct icmp6_hdr                *icmp6;
-       struct nd_neighbor_advert       *nd_na;
-       struct nd_neighbor_solicit      *nd_ns;
-       union nd_opts                    ndopts;
-       uint8_t                         *lladdr;
-       int                              lladdrlen;
-       int                              icmp6len = m->m_pkthdr.len - *offset;
-
-       IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, *offset, sizeof(*icmp6));
-       if (icmp6 == NULL)
-               goto failed;
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_ADVERT:
-               if (icmp6len < sizeof(struct nd_neighbor_advert))
-                       goto failed;
-               break;
-       case ND_NEIGHBOR_SOLICIT:
-               if (icmp6len < sizeof(struct nd_neighbor_solicit))
-                       goto failed;
-               break;
-       }
-
-       swfcl->swfcl_nd6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_nd6 == NULL)
-               goto failed;
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_ADVERT:
-               IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m,
-                   *offset, icmp6len);
-
-               if (nd_na == NULL)
-                       goto failed;
-
-               swfcl->swfcl_nd6->nd6_target = nd_na->nd_na_target;
-               icmp6len -= sizeof(*nd_na);
-               nd6_option_init(nd_na + 1, icmp6len, &ndopts);
-               if (nd6_options(&ndopts) < 0)
-                       goto failed;
-
-               if (!ndopts.nd_opts_tgt_lladdr)
-                       goto failed;
-
-               lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
-               lladdrlen = (ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3) - 2;
-
-               /* switch(4) only supports Ethernet interfaces */
-               if (lladdrlen != ETHER_ADDR_LEN)
-                       goto failed;
-               memcpy(swfcl->swfcl_nd6->nd6_lladdr, lladdr, ETHER_ADDR_LEN);
-               break;
-       case ND_NEIGHBOR_SOLICIT:
-               IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m,
-                   *offset, icmp6len);
-               if (nd_ns == NULL)
-                       goto failed;
-               swfcl->swfcl_nd6->nd6_target = nd_ns->nd_ns_target;
-               icmp6len -= sizeof(*nd_ns);
-
-               nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
-               if (nd6_options(&ndopts) < 0)
-                       goto failed;
-
-               if (!ndopts.nd_opts_src_lladdr)
-                       goto failed;
-               lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
-               lladdrlen = (ndopts.nd_opts_src_lladdr->nd_opt_len << 3) - 2;
-
-               /* switch(4) only supports Ethernet interfaces */
-               if (lladdrlen != ETHER_ADDR_LEN)
-                       goto failed;
-               memcpy(swfcl->swfcl_nd6->nd6_lladdr, lladdr, ETHER_ADDR_LEN);
-
-               break;
-       }
-
-       return (m);
-
- failed:
-       m_freem(m);
-       return (NULL);
-}
-
-struct mbuf *
-switch_flow_classifier_icmpv6(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct icmp6_hdr        *icmp6;
-
-       swfcl->swfcl_icmpv6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_icmpv6 == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, *offset, sizeof(*icmp6));
-       if (icmp6 == NULL)
-               return (NULL); /* m was already freed */
-
-       swfcl->swfcl_icmpv6->icmpv6_type = icmp6->icmp6_type;
-       swfcl->swfcl_icmpv6->icmpv6_code = icmp6->icmp6_code;
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_SOLICIT:
-       case ND_NEIGHBOR_ADVERT:
-               return switch_flow_classifier_nd6(m, offset, swfcl);
-       }
-
-       return (m);
-}
-#endif /* INET6 */
-
-struct mbuf *
-switch_flow_classifier_ipv4(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct ip       *ip;
-
-       swfcl->swfcl_ipv4 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_ipv4 == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + sizeof(*ip)) &&
-           (m = m_pullup(m, *offset + sizeof(*ip))) == NULL)
-               return (NULL);
-
-       ip = (struct ip *)((m)->m_data + *offset);
-
-       swfcl->swfcl_ipv4->ipv4_tos = ip->ip_tos;
-       swfcl->swfcl_ipv4->ipv4_ttl = ip->ip_ttl;
-       swfcl->swfcl_ipv4->ipv4_proto = ip->ip_p;
-
-       memcpy(&swfcl->swfcl_ipv4->ipv4_src, &ip->ip_src.s_addr,
-           sizeof(uint32_t));
-       memcpy(&swfcl->swfcl_ipv4->ipv4_dst, &ip->ip_dst.s_addr,
-           sizeof(uint32_t));
-
-       *offset += (ip->ip_hl << 2);
-
-       switch (ip->ip_p) {
-       case IPPROTO_UDP:
-               return switch_flow_classifier_udp(m, offset, swfcl);
-       case IPPROTO_TCP:
-               return switch_flow_classifier_tcp(m, offset, swfcl);
-       case IPPROTO_ICMP:
-               return switch_flow_classifier_icmpv4(m, offset, swfcl);
-       }
-
-       return (m);
-}
-
-#ifdef INET6
-struct mbuf *
-switch_flow_classifier_ipv6(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct ip6_hdr  *ip6;
-
-       swfcl->swfcl_ipv6 = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_ipv6 == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + sizeof(*ip6)) &&
-           (m = m_pullup(m, *offset + sizeof(*ip6))) == NULL)
-               return (NULL);
-
-       ip6 = (struct ip6_hdr *)((m)->m_data + *offset);
-
-       swfcl->swfcl_ipv6->ipv6_src = ip6->ip6_src;
-       swfcl->swfcl_ipv6->ipv6_dst = ip6->ip6_dst;
-       swfcl->swfcl_ipv6->ipv6_flow_label =
-           (ip6->ip6_flow & IPV6_FLOWLABEL_MASK);
-       swfcl->swfcl_ipv6->ipv6_tclass = (ntohl(ip6->ip6_flow) >> 20);
-       swfcl->swfcl_ipv6->ipv6_hlimit = ip6->ip6_hlim;
-       swfcl->swfcl_ipv6->ipv6_nxt = ip6->ip6_nxt;
-
-       *offset += sizeof(*ip6);
-
-       switch (ip6->ip6_nxt) {
-       case IPPROTO_UDP:
-               return switch_flow_classifier_udp(m, offset, swfcl);
-       case IPPROTO_TCP:
-               return switch_flow_classifier_tcp(m, offset, swfcl);
-       case IPPROTO_ICMPV6:
-               return switch_flow_classifier_icmpv6(m, offset, swfcl);
-       }
-
-       return (m);
-}
-#endif /* INET6 */
-
-struct mbuf *
-switch_flow_classifier_arp(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct ether_arp        *ea;
-
-       swfcl->swfcl_arp = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_arp == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < (*offset + sizeof(*ea)) &&
-           (m = m_pullup(m, *offset + sizeof(*ea))) == NULL)
-               return (NULL);
-
-       ea = (struct ether_arp *)((m)->m_data + *offset);
-
-       swfcl->swfcl_arp->_arp_op = ea->arp_op;
-
-       memcpy(swfcl->swfcl_arp->arp_sha, &ea->arp_sha, ETHER_ADDR_LEN);
-       memcpy(swfcl->swfcl_arp->arp_tha, &ea->arp_tha, ETHER_ADDR_LEN);
-       memcpy(&swfcl->swfcl_arp->arp_sip, &ea->arp_spa, sizeof(uint32_t));
-       memcpy(&swfcl->swfcl_arp->arp_tip, &ea->arp_tpa, sizeof(uint32_t));
-
-       return (m);
-}
-
-struct mbuf *
-switch_flow_classifier_ether(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct ether_header             *eh;
-       struct ether_vlan_header        *evl;
-       uint16_t                         ether_type;
-
-       swfcl->swfcl_ether = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_ether == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (m->m_len < sizeof(*eh) && (m = m_pullup(m, sizeof(*eh))) == NULL)
-               return (NULL);
-       eh = mtod(m, struct ether_header *);
-
-       memcpy(swfcl->swfcl_ether->eth_src, eh->ether_shost, ETHER_ADDR_LEN);
-       memcpy(swfcl->swfcl_ether->eth_dst, eh->ether_dhost, ETHER_ADDR_LEN);
-
-       if ((m->m_flags & M_VLANTAG) ||
-           (ntohs(eh->ether_type) == ETHERTYPE_VLAN) ||
-           (ntohs(eh->ether_type) == ETHERTYPE_QINQ)) {
-               swfcl->swfcl_vlan = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (swfcl->swfcl_vlan == NULL) {
-                       m_freem(m);
-                       return (NULL);
-               }
-       }
-
-       if (m->m_flags & M_VLANTAG) {
-               /*
-                * Hardware VLAN tagging is only supported for 801.1Q VLAN,
-                * but not for 802.1ad QinQ.
-                */
-               swfcl->swfcl_vlan->vlan_tpid = htons(ETHERTYPE_VLAN);
-               swfcl->swfcl_vlan->vlan_vid =
-                   htons(EVL_VLANOFTAG(m->m_pkthdr.ether_vtag));
-               swfcl->swfcl_vlan->vlan_pcp =
-                   EVL_PRIOFTAG(m->m_pkthdr.ether_vtag);
-               ether_type = eh->ether_type;
-               *offset += sizeof(*eh);
-       } else if (ntohs(eh->ether_type) == ETHERTYPE_VLAN) {
-               if (m->m_len < sizeof(*evl) &&
-                   (m = m_pullup(m, sizeof(*evl))) == NULL)
-                       return (NULL);
-               evl = mtod(m, struct ether_vlan_header *);
-
-               /*
-                * Software VLAN tagging is currently only supported for
-                * 801.1Q VLAN, but not for 802.1ad QinQ.
-                */
-               swfcl->swfcl_vlan->vlan_tpid = htons(ETHERTYPE_VLAN);
-               swfcl->swfcl_vlan->vlan_vid =
-                   (evl->evl_tag & htons(EVL_VLID_MASK));
-               swfcl->swfcl_vlan->vlan_pcp =
-                   EVL_PRIOFTAG(ntohs(evl->evl_tag));
-               ether_type = evl->evl_proto;
-               *offset += sizeof(*evl);
-       } else {
-               ether_type = eh->ether_type;
-               *offset += sizeof(*eh);
-       }
-
-       swfcl->swfcl_ether->eth_type = ether_type;
-
-       ether_type = ntohs(ether_type);
-       switch (ether_type) {
-       case ETHERTYPE_ARP:
-               return switch_flow_classifier_arp(m, offset, swfcl);
-       case ETHERTYPE_IP:
-               return switch_flow_classifier_ipv4(m, offset, swfcl);
-#ifdef INET6
-       case ETHERTYPE_IPV6:
-               return switch_flow_classifier_ipv6(m, offset, swfcl);
-#endif /* INET6 */
-       case ETHERTYPE_MPLS:
-               /* unsupported yet */
-               break;
-       }
-
-       return (m);
-}
-
-struct mbuf *
-switch_flow_classifier_tunnel(struct mbuf *m, int *offset,
-    struct switch_flow_classify *swfcl)
-{
-       struct bridge_tunneltag *brtag;
-
-       if ((brtag = bridge_tunnel(m)) == NULL)
-               goto out;
-
-       if ((brtag->brtag_peer.sa.sa_family != AF_INET) &&
-           (brtag->brtag_peer.sa.sa_family != AF_INET6))
-               goto out;
-
-       swfcl->swfcl_tunnel = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-       if (swfcl->swfcl_tunnel == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       swfcl->swfcl_tunnel->tun_af = brtag->brtag_peer.sa.sa_family;
-       swfcl->swfcl_tunnel->tun_key = htobe64(brtag->brtag_id);
-       if (swfcl->swfcl_tunnel->tun_af == AF_INET) {
-               swfcl->swfcl_tunnel->tun_ipv4_src =
-                   brtag->brtag_local.sin.sin_addr;
-               swfcl->swfcl_tunnel->tun_ipv4_dst =
-                   brtag->brtag_peer.sin.sin_addr;
-       } else {
-               swfcl->swfcl_tunnel->tun_ipv6_src =
-                   brtag->brtag_local.sin6.sin6_addr;
-               swfcl->swfcl_tunnel->tun_ipv6_dst =
-                   brtag->brtag_peer.sin6.sin6_addr;
-       }
-       bridge_tunneluntag(m);
- out:
-       return switch_flow_classifier_ether(m, offset, swfcl);
-}
-
-struct mbuf *
-switch_flow_classifier(struct mbuf *m, uint32_t in_port,
-    struct switch_flow_classify *swfcl)
-{
-       int      offset = 0;
-
-       memset(swfcl, 0, sizeof(*swfcl));
-       swfcl->swfcl_in_port = in_port;
-
-       return switch_flow_classifier_tunnel(m, &offset, swfcl);
-}
-
-void
-switch_flow_classifier_dump(struct switch_softc *sc,
-    struct switch_flow_classify *swfcl)
-{
-       char    saddr[INET6_ADDRSTRLEN], daddr[INET6_ADDRSTRLEN];
-
-       log(LOG_DEBUG, "%s: ", sc->sc_if.if_xname);
-       addlog("in_port(%u),", swfcl->swfcl_in_port);
-
-       if (swfcl->swfcl_tunnel) {
-               if (swfcl->swfcl_tunnel->tun_af == AF_INET) {
-                       inet_ntop(AF_INET,
-                           (void *)&swfcl->swfcl_tunnel->tun_ipv4_src,
-                           saddr, sizeof(saddr));
-                       inet_ntop(AF_INET,
-                           (void *)&swfcl->swfcl_tunnel->tun_ipv4_dst,
-                           daddr, sizeof(daddr));
-                       addlog("tun_ipv4_src(%s),tun_ipv4_dst(%s),"
-                           "tun_id(%llu),", saddr, daddr,
-                           be64toh(swfcl->swfcl_tunnel->tun_key));
-               } else if (swfcl->swfcl_tunnel->tun_af == AF_INET6) {
-                       inet_ntop(AF_INET6,
-                           (void *)&swfcl->swfcl_tunnel->tun_ipv6_src,
-                           saddr, sizeof(saddr));
-                       inet_ntop(AF_INET6,
-                           (void *)&swfcl->swfcl_tunnel->tun_ipv6_dst,
-                           daddr, sizeof(daddr));
-                       addlog("tun_ipv6_src(%s) tun_ipv6_dst(%s),"
-                           "tun_id(%llu),", saddr, daddr,
-                           be64toh(swfcl->swfcl_tunnel->tun_key));
-               }
-       }
-
-       if (swfcl->swfcl_vlan) {
-               addlog("vlan_tpid(0x%0x4x),vlan_pcp(%u),vlan_vid(%u),",
-                   ntohs(swfcl->swfcl_vlan->vlan_tpid),
-                   swfcl->swfcl_vlan->vlan_pcp,
-                   ntohs(swfcl->swfcl_vlan->vlan_vid));
-       }
-
-       if (swfcl->swfcl_ether) {
-               addlog("eth_dst(%s),eth_src(%s),eth_type(0x%04x)",
-                   ether_sprintf(swfcl->swfcl_ether->eth_dst),
-                   ether_sprintf(swfcl->swfcl_ether->eth_src),
-                   ntohs(swfcl->swfcl_ether->eth_type));
-       }
-
-       if (swfcl->swfcl_arp) {
-               inet_ntop(AF_INET, (void *)&swfcl->swfcl_arp->arp_sip,
-                   saddr, sizeof(saddr));
-               inet_ntop(AF_INET, (void *)&swfcl->swfcl_arp->arp_tip,
-                   daddr, sizeof(daddr));
-               addlog("arp_op(%x),arp_tha(%s),arp_sha(%s),arp_sip(%s),"
-                   "arp_tip(%s),", swfcl->swfcl_arp->_arp_op,
-                   ether_sprintf(swfcl->swfcl_arp->arp_tha),
-                   ether_sprintf(swfcl->swfcl_arp->arp_sha), saddr, daddr);
-       }
-
-       if (swfcl->swfcl_ipv4) {
-               inet_ntop(AF_INET, (void *)&swfcl->swfcl_ipv4->ipv4_src,
-                   saddr, sizeof(saddr));
-               inet_ntop(AF_INET, (void *)&swfcl->swfcl_ipv4->ipv4_dst,
-                   daddr, sizeof(daddr));
-               addlog("ip_proto(%u),ip_tos(%u),ip_ttl(%u),ip_src(%s),"
-                   "ip_dst(%s),", swfcl->swfcl_ipv4->ipv4_proto,
-                   swfcl->swfcl_ipv4->ipv4_tos, swfcl->swfcl_ipv4->ipv4_ttl,
-                   saddr, daddr);
-       }
-
-       if (swfcl->swfcl_ipv6) {
-               inet_ntop(AF_INET6, (void *)&swfcl->swfcl_ipv6->ipv6_src,
-                   saddr, sizeof(saddr));
-               inet_ntop(AF_INET6, (void *)&swfcl->swfcl_ipv6->ipv6_dst,
-                   daddr, sizeof(daddr));
-               addlog("ip6_nxt(%u),ip6_flow_label(%u),ip6_tclass(%d),"
-                   "ip6_hlimit(%u),ip6_src(%s),ip6_dst(%s),",
-                   swfcl->swfcl_ipv6->ipv6_nxt,
-                   ntohl(swfcl->swfcl_ipv6->ipv6_flow_label),
-                   swfcl->swfcl_ipv6->ipv6_tclass,
-                   swfcl->swfcl_ipv6->ipv6_hlimit, saddr, daddr);
-       }
-
-       if (swfcl->swfcl_icmpv4) {
-               addlog("icmp_type(%u),icmp_code(%u),",
-                   swfcl->swfcl_icmpv4->icmpv4_type,
-                   swfcl->swfcl_icmpv4->icmpv4_code);
-       }
-
-       if (swfcl->swfcl_icmpv6) {
-               addlog("icmp6_type(%u),icmp6_code(%u),",
-                   swfcl->swfcl_icmpv6->icmpv6_type,
-                   swfcl->swfcl_icmpv6->icmpv6_code);
-       }
-
-       if (swfcl->swfcl_nd6) {
-               inet_ntop(AF_INET6, (void *)&swfcl->swfcl_nd6->nd6_target,
-                   saddr, sizeof(saddr));
-               addlog("nd_target(%s),nd_lladdr(%s),", saddr,
-                   ether_sprintf(swfcl->swfcl_nd6->nd6_lladdr));
-       }
-
-       if (swfcl->swfcl_tcp) {
-               addlog("tcp_src(%u),tcp_dst(%u),tcp_flags(%x),",
-                   ntohs(swfcl->swfcl_tcp->tcp_src),
-                   ntohs(swfcl->swfcl_tcp->tcp_dst),
-                   swfcl->swfcl_tcp->tcp_flags);
-       }
-
-       if (swfcl->swfcl_udp) {
-               addlog("udp_src(%u),udp_dst(%u),",
-                   ntohs(swfcl->swfcl_udp->udp_src),
-                   ntohs(swfcl->swfcl_udp->udp_dst));
-       }
-
-       addlog("\n");
-}
-
-int
-switch_mtap(caddr_t arg, struct mbuf *m, int dir, uint64_t datapath_id)
-{
-#if NBPFILTER > 0
-       struct dlt_openflow_hdr  of;
-
-       of.of_datapath_id = htobe64(datapath_id);
-       of.of_direction = htonl(dir == BPF_DIRECTION_IN ?
-           DLT_OPENFLOW_TO_SWITCH : DLT_OPENFLOW_TO_CONTROLLER);
-
-       return (bpf_mtap_hdr(arg, (caddr_t)&of, sizeof(of), m, dir));
-#else
-       return (0);
-#endif
-}
-
-int
-ofp_split_mbuf(struct mbuf *m, struct mbuf **mtail)
-{
-       uint16_t                 ohlen;
-
-       *mtail = NULL;
-
- again:
-       /* We need more data. */
-       KASSERT(m->m_flags & M_PKTHDR);
-       if (m->m_pkthdr.len < sizeof(struct ofp_header))
-               return (-1);
-
-       m_copydata(m, offsetof(struct ofp_header, oh_length), sizeof(ohlen),
-           &ohlen);
-       ohlen = ntohs(ohlen);
-
-       /* We got an invalid packet header, skip it. */
-       if (ohlen < sizeof(struct ofp_header)) {
-               m_adj(m, sizeof(struct ofp_header));
-               goto again;
-       }
-
-       /* Nothing to split. */
-       if (m->m_pkthdr.len == ohlen)
-               return (0);
-       else if (m->m_pkthdr.len < ohlen)
-               return (-1);
-
-       *mtail = m_split(m, ohlen, M_NOWAIT);
-       /* No memory, try again later. */
-       if (*mtail == NULL)
-               return (-1);
-
-       return (0);
-}
-
-void
-switch_take(void *unused)
-{
-       return;
-}
-
-void
-switch_rele(void *unused)
-{
-       return;
-}
diff --git a/sys/net/if_switch.h b/sys/net/if_switch.h
deleted file mode 100644 (file)
index f8bd6df..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-/*     $OpenBSD: if_switch.h,v 1.12 2019/11/06 03:51:26 dlg Exp $      */
-
-/*
- * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
- * Copyright (c) 2016 Reyk Floeter <reyk@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef _NET_IF_SWITCH_H_
-#define _NET_IF_SWITCH_H_
-
-/* capabilities for switch(4) */
-#define SWITCH_CAP_STP         0x0001
-#define SWITCH_CAP_LEARNING    0x0002
-#define SWITCH_CAP_OFP         0x0004
-
-#ifdef _KERNEL
-
-struct switch_field_tunnel {
-       uint32_t         tun_af;
-       struct in_addr   tun_ipv4_src;
-       struct in_addr   tun_ipv4_dst;
-       struct in6_addr  tun_ipv6_src;
-       struct in6_addr  tun_ipv6_dst;
-       uint64_t         tun_key;
-};
-
-struct switch_field_ether {
-       uint8_t          eth_src[ETHER_ADDR_LEN];
-       uint8_t          __pad_eth_src[2];
-       uint8_t          eth_dst[ETHER_ADDR_LEN];
-       uint8_t          __pad_eth_dst[2];
-       uint16_t         eth_type;
-       uint8_t          __pad_eth_type[2];
-};
-
-struct switch_field_vlan {
-       uint16_t         vlan_tpid;
-       uint16_t         vlan_vid;
-       uint16_t         vlan_pcp;
-       uint8_t          __pad_vlan_pcp[2];
-};
-
-struct switch_field_ipv4 {
-       uint32_t         ipv4_src;
-       uint32_t         ipv4_dst;
-       uint8_t          ipv4_proto;
-       uint8_t          ipv4_tos;
-       uint8_t          ipv4_ttl;
-       uint8_t          ipv4_frag;
-};
-
-struct switch_field_ipv6 {
-       struct in6_addr  ipv6_src;
-       struct in6_addr  ipv6_dst;
-       uint32_t         ipv6_flow_label;
-       uint8_t          ipv6_nxt;
-       uint8_t          ipv6_tclass;
-       uint8_t          ipv6_hlimit;
-       uint8_t          ipv6_frag;
-};
-
-struct switch_field_arp {
-       uint16_t         _arp_op;
-       uint8_t          __pad_arp_op[2];
-       uint8_t          arp_sha[ETHER_ADDR_LEN];
-       uint8_t          __pad_arp_sha[2];
-       uint8_t          arp_tha[ETHER_ADDR_LEN];
-       uint8_t          __pad_arp_tha[2];
-       uint32_t         arp_sip;
-       uint32_t         arp_tip;
-};
-
-struct switch_field_nd6 {
-       struct in6_addr  nd6_target;
-       uint8_t          nd6_lladdr[ETHER_ADDR_LEN];
-       uint8_t          __pad_nd6_lladdr[2];
-};
-
-struct switch_field_icmpv4 {
-       uint8_t          icmpv4_type;
-       uint8_t          icmpv4_code;
-       uint8_t          __pad[2];
-};
-
-struct switch_field_icmpv6 {
-       uint8_t          icmpv6_type;
-       uint8_t          icmpv6_code;
-       uint8_t          __pad[2];
-};
-
-struct switch_field_tcp {
-       uint16_t         tcp_src;
-       uint16_t         tcp_dst;
-       uint8_t          tcp_flags;
-       uint8_t          __pad[3];
-};
-
-struct switch_field_udp {
-       uint16_t         udp_src;
-       uint16_t         udp_dst;
-};
-
-struct switch_field_sctp {
-       uint16_t         sctp_src;
-       uint16_t         sctp_dst;
-};
-
-union switch_field {
-       struct switch_field_tunnel       swfcl_tunnel;
-       struct switch_field_ether        swfcl_ether;
-       struct switch_field_vlan         swfcl_vlan;
-       struct switch_field_ipv4         swfcl_ipv4;
-       struct switch_field_ipv6         swfcl_ipv6;
-       struct switch_field_arp          swfcl_arp;
-       struct switch_field_nd6          swfcl_nd6;
-       struct switch_field_icmpv4       swfcl_icmpv4;
-       struct switch_field_icmpv6       swfcl_icmpv6;
-       struct switch_field_tcp          swfcl_tcp;
-       struct switch_field_udp          swfcl_udp;
-       struct switch_field_sctp         swfcl_sctp;
-};
-
-struct switch_flow_classify {
-       uint64_t                         swfcl_flow_hash;
-
-       /*
-        * Pipeline field on OpenFlow switch specific
-        */
-       uint64_t                         swfcl_metadata;
-       uint64_t                         swfcl_cookie;
-       uint8_t                          swfcl_table_id;
-
-       /*
-        * Classify field without protocol headers
-        */
-       uint32_t                         swfcl_in_port;
-
-       /*
-        * Classify field from protocol headers
-        */
-       struct switch_field_tunnel      *swfcl_tunnel;
-       struct switch_field_ether       *swfcl_ether;
-       struct switch_field_vlan        *swfcl_vlan;
-       struct switch_field_ipv4        *swfcl_ipv4;
-       struct switch_field_ipv6        *swfcl_ipv6;
-       struct switch_field_arp         *swfcl_arp;
-       struct switch_field_nd6         *swfcl_nd6;
-       struct switch_field_icmpv4      *swfcl_icmpv4;
-       struct switch_field_icmpv6      *swfcl_icmpv6;
-       struct switch_field_tcp         *swfcl_tcp;
-       struct switch_field_udp         *swfcl_udp;
-       struct switch_field_sctp        *swfcl_sctp;
-};
-
-struct switch_softc;
-
-struct switch_port {
-       TAILQ_ENTRY(switch_port)         swpo_list_next;
-       TAILQ_ENTRY(switch_port)         swpo_fwdp_next;
-       uint32_t                         swpo_port_no;
-       uint32_t                         swpo_ifindex;
-       struct timespec                  swpo_appended;
-       struct switch_softc             *swpo_switch;
-       uint32_t                         swpo_flags;
-       uint32_t                         swpo_protected;
-       struct task                      swpo_dtask;
-       void                            (*swop_bk_start)(struct ifnet *);
-};
-
-TAILQ_HEAD(switch_fwdp_queue, switch_port);
-
-struct switch_dev {
-       struct mbuf             *swdev_lastm;
-       struct mbuf             *swdev_inputm;
-       struct mbuf_queue        swdev_outq;
-       struct selinfo           swdev_rsel;
-       struct selinfo           swdev_wsel;
-       int                      swdev_waiting;
-       void                    (*swdev_init)(struct switch_softc *);
-       int                     (*swdev_input)(struct switch_softc *,
-                                   struct mbuf *);
-       int                     (*swdev_output)(struct switch_softc *,
-                                   struct mbuf *);
-};
-
-struct switch_softc {
-       struct ifnet                     sc_if;
-       int                              sc_unit;
-       uint32_t                         sc_capabilities;
-       struct switch_dev               *sc_swdev;              /* char device */
-       struct bstp_state               *sc_stp;                /* STP state */
-       struct swofp_ofs                *sc_ofs;                /* OpenFlow */
-       caddr_t                          sc_ofbpf;              /* DLT_OPENFLOW */
-       TAILQ_HEAD(,switch_port)         sc_swpo_list;          /* port */
-       LIST_ENTRY(switch_softc)         sc_switch_next;        /* switch link */
-       void                            (*switch_process_forward)(
-           struct switch_softc *, struct switch_flow_classify *,
-           struct mbuf *);
-};
-
-/* if_switch.c */
-struct switch_softc
-       *switch_lookup(int);
-void    switch_port_egress(struct switch_softc *, struct switch_fwdp_queue *,
-           struct mbuf *);
-int     switch_swfcl_dup(struct switch_flow_classify *,
-           struct switch_flow_classify *);
-void    switch_swfcl_free(struct switch_flow_classify *);
-struct mbuf
-       *switch_flow_classifier(struct mbuf *, uint32_t,
-           struct switch_flow_classify *);
-int     switch_mtap(caddr_t, struct mbuf *, int, uint64_t);
-int     ofp_split_mbuf(struct mbuf *, struct mbuf **);
-
-/* switchctl.c */
-void    switch_dev_destroy(struct switch_softc *);
-
-/* in switchofp.c */
-void    swofp_attach(void);
-int     swofp_create(struct switch_softc *);
-int     swofp_init(struct switch_softc *);
-void    swofp_destroy(struct switch_softc *);
-int     swofp_ioctl(struct ifnet *, unsigned long, caddr_t);
-uint32_t
-        swofp_assign_portno(struct switch_softc *, uint32_t);
-
-#endif /* _KERNEL */
-#endif /* _NET_IF_SWITCH_H_ */
diff --git a/sys/net/switchctl.c b/sys/net/switchctl.c
deleted file mode 100644 (file)
index 94eacec..0000000
+++ /dev/null
@@ -1,475 +0,0 @@
-/*     $OpenBSD: switchctl.c,v 1.23 2020/12/25 12:59:53 visa Exp $     */
-
-/*
- * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
- * Copyright (c) 2015, 2016 YASUOKA Masahiko <yasuoka@openbsd.org>
- * Copyright (c) 2015, 2016 Reyk Floeter <reyk@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/selinfo.h>
-#include <sys/rwlock.h>
-#include <sys/proc.h>
-
-#include <net/if.h>
-#include <net/rtable.h>
-
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-
-#include <net/if_switch.h>
-
-extern struct rwlock   switch_ifs_lk;
-
-/*
- * device part of switch(4)
- */
-#include <sys/poll.h>
-#include <sys/selinfo.h>
-#include <sys/vnode.h>
-
-struct switch_softc *switch_dev2sc(dev_t);
-int    switchopen(dev_t, int, int, struct proc *);
-int    switchread(dev_t, struct uio *, int);
-int    switchwrite(dev_t, struct uio *, int);
-int    switchioctl(dev_t, u_long, caddr_t, int, struct proc *);
-int    switchclose(dev_t, int, int, struct proc *);
-int    switchpoll(dev_t, int, struct proc *);
-int    switchkqfilter(dev_t, struct knote *);
-void   filt_switch_rdetach(struct knote *);
-int    filt_switch_read(struct knote *, long);
-void   filt_switch_wdetach(struct knote *);
-int    filt_switch_write(struct knote *, long);
-int    switch_dev_output(struct switch_softc *, struct mbuf *);
-void   switch_dev_wakeup(struct switch_softc *);
-
-const struct filterops switch_rd_filtops = {
-       .f_flags        = FILTEROP_ISFD,
-       .f_attach       = NULL,
-       .f_detach       = filt_switch_rdetach,
-       .f_event        = filt_switch_read,
-};
-
-const struct filterops switch_wr_filtops = {
-       .f_flags        = FILTEROP_ISFD,
-       .f_attach       = NULL,
-       .f_detach       = filt_switch_wdetach,
-       .f_event        = filt_switch_write,
-};
-
-struct switch_softc *
-switch_dev2sc(dev_t dev)
-{
-       struct switch_softc     *sc;
-
-       rw_enter_read(&switch_ifs_lk);
-       sc = switch_lookup(minor(dev));
-       rw_exit_read(&switch_ifs_lk);
-
-       return (sc);
-}
-
-int
-switchopen(dev_t dev, int flags, int mode, struct proc *p)
-{
-       struct switch_softc     *sc;
-       char                     name[IFNAMSIZ];
-       int                      rv, s, error = 0;
-       unsigned int             rdomain = rtable_l2(p->p_p->ps_rtableid);
-
-       if ((sc = switch_dev2sc(dev)) == NULL) {
-               snprintf(name, sizeof(name), "switch%d", minor(dev));
-               rv = if_clone_create(name, rdomain);
-               if (rv != 0)
-                       return (rv);
-               if ((sc = switch_dev2sc(dev)) == NULL)
-                       return (ENXIO);
-       }
-
-       rw_enter_write(&switch_ifs_lk);
-       if (sc->sc_swdev != NULL) {
-               error = EBUSY;
-               goto failed;
-       }
-
-       if ((sc->sc_swdev = malloc(sizeof(struct switch_dev), M_DEVBUF,
-           M_DONTWAIT|M_ZERO)) == NULL ) {
-               error = ENOBUFS;
-               goto failed;
-       }
-
-       s = splnet();
-       mq_init(&sc->sc_swdev->swdev_outq, 128, IPL_NET);
-
-       sc->sc_swdev->swdev_output = switch_dev_output;
-       if (sc->sc_capabilities & SWITCH_CAP_OFP)
-               swofp_init(sc);
-
-       splx(s);
-
- failed:
-       rw_exit_write(&switch_ifs_lk);
-       return (error);
-
-}
-
-int
-switchread(dev_t dev, struct uio *uio, int ioflag)
-{
-       struct switch_softc     *sc;
-       struct mbuf             *m;
-       u_int                    len;
-       int                      s, error = 0;
-
-       sc = switch_dev2sc(dev);
-       if (sc == NULL)
-               return (ENXIO);
-
-       if (sc->sc_swdev->swdev_lastm != NULL) {
-               m = sc->sc_swdev->swdev_lastm;
-               sc->sc_swdev->swdev_lastm = NULL;
-               goto skip_dequeue;
-       }
-
- dequeue_next:
-       s = splnet();
-       while ((m = mq_dequeue(&sc->sc_swdev->swdev_outq)) == NULL) {
-               if (ISSET(ioflag, IO_NDELAY)) {
-                       error = EWOULDBLOCK;
-                       goto failed;
-               }
-               sc->sc_swdev->swdev_waiting = 1;
-               error = tsleep_nsec(sc, (PZERO + 1)|PCATCH, "switchread",
-                   INFSLP);
-               if (error != 0)
-                       goto failed;
-               /* sc might be deleted while sleeping */
-               sc = switch_dev2sc(dev);
-               if (sc == NULL) {
-                       error = ENXIO;
-                       goto failed;
-               }
-       }
-       splx(s);
-
- skip_dequeue:
-       while (uio->uio_resid > 0) {
-               len = ulmin(uio->uio_resid, m->m_len);
-               if ((error = uiomove(mtod(m, caddr_t), len, uio)) != 0) {
-                       /* Save it so user can recover from EFAULT. */
-                       sc->sc_swdev->swdev_lastm = m;
-                       return (error);
-               }
-
-               /* Handle partial reads. */
-               if (uio->uio_resid == 0) {
-                       if (len < m->m_len)
-                               m_adj(m, len);
-                       else
-                               m = m_free(m);
-                       sc->sc_swdev->swdev_lastm = m;
-                       break;
-               }
-
-               /*
-                * After consuming data from this mbuf test if we
-                * have to dequeue a new chain.
-                */
-               m = m_free(m);
-               if (m == NULL)
-                       goto dequeue_next;
-       }
-
-       return (0);
-failed:
-       splx(s);
-       return (error);
-}
-
-int
-switchwrite(dev_t dev, struct uio *uio, int ioflag)
-{
-       struct switch_softc     *sc = NULL;
-       struct mbuf             *m, *n, *mhead, *mtail = NULL;
-       int                      s, error, trailing;
-       size_t                   len;
-
-       if (uio->uio_resid == 0)
-               return (0);
-
-       len = uio->uio_resid;
-
-       sc = switch_dev2sc(dev);
-       if (sc == NULL)
-               return (ENXIO);
-
-       if (sc->sc_swdev->swdev_inputm == NULL) {
-               MGETHDR(m, M_DONTWAIT, MT_DATA);
-               if (m == NULL)
-                       return (ENOBUFS);
-               if (len >= MHLEN) {
-                       MCLGETL(m, M_DONTWAIT, MIN(MAXMCLBYTES, len));
-                       if ((m->m_flags & M_EXT) == 0) {
-                               m_free(m);
-                               return (ENOBUFS);
-                       }
-               }
-               mhead = m;
-
-               /* m_trailingspace() uses this to calculate space. */
-               m->m_len = 0;
-       } else {
-               /* Recover the mbuf from the last write and get its tail. */
-               mhead = sc->sc_swdev->swdev_inputm;
-               for (m = mhead; m->m_next != NULL; m = m->m_next)
-                       /* NOTHING */;
-
-               sc->sc_swdev->swdev_inputm = NULL;
-       }
-       KASSERT(mhead->m_flags & M_PKTHDR);
-
-       while (len) {
-               trailing = ulmin(m_trailingspace(m), len);
-               if ((error = uiomove(mtod(m, caddr_t) + m->m_len, trailing,
-                   uio)) != 0)
-                       goto save_return;
-
-               len -= trailing;
-               mhead->m_pkthdr.len += trailing;
-               m->m_len += trailing;
-               if (len == 0)
-                       break;
-
-               MGET(n, M_DONTWAIT, MT_DATA);
-               if (n == NULL) {
-                       error = ENOBUFS;
-                       goto save_return;
-               }
-               if (len >= MLEN) {
-                       MCLGETL(n, M_DONTWAIT, MIN(MAXMCLBYTES, len));
-                       if ((n->m_flags & M_EXT) == 0) {
-                               m_free(n);
-                               error = ENOBUFS;
-                               goto save_return;
-                       }
-               }
-               n->m_len = 0;
-
-               m->m_next = n;
-               m = n;
-       }
-
-       /* Loop until there is no more complete OFP packets. */
-       while (ofp_split_mbuf(mhead, &mtail) == 0) {
-               s = splnet();
-               sc->sc_swdev->swdev_input(sc, mhead);
-               splx(s);
-
-               /* We wrote everything, just quit. */
-               if (mtail == NULL)
-                       return (0);
-
-               mhead = mtail;
-       }
-
-       /* Save the head, because ofp_split_mbuf failed. */
-       sc->sc_swdev->swdev_inputm = mhead;
-
-       return (0);
-
- save_return:
-       /* Save it so user can recover from errors later. */
-       sc->sc_swdev->swdev_inputm = mhead;
-       return (error);
-}
-
-int
-switchioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
-{
-       int                      error;
-
-       switch (cmd) {
-       case FIONBIO:
-       case FIOASYNC:
-       case FIONREAD:
-               return (0);
-       default:
-               error = ENOTTY;
-               break;
-       }
-
-       return (error);
-}
-
-int
-switchclose(dev_t dev, int flags, int mode, struct proc *p)
-{
-       struct switch_softc     *sc;
-
-       rw_enter_write(&switch_ifs_lk);
-       sc = switch_lookup(minor(dev));
-       if (sc != NULL && sc->sc_swdev != NULL) {
-               m_freem(sc->sc_swdev->swdev_lastm);
-               m_freem(sc->sc_swdev->swdev_inputm);
-               mq_purge(&sc->sc_swdev->swdev_outq);
-               free(sc->sc_swdev, M_DEVBUF, sizeof(struct switch_dev));
-               sc->sc_swdev = NULL;
-       }
-       rw_exit_write(&switch_ifs_lk);
-
-       return (0);
-}
-
-void
-switch_dev_destroy(struct switch_softc *sc)
-{
-       int      s;
-
-       if (sc->sc_swdev == NULL)
-               return;
-       rw_enter_write(&switch_ifs_lk);
-       if (sc->sc_swdev != NULL) {
-               switch_dev_wakeup(sc);
-
-               s = splhigh();
-               klist_invalidate(&sc->sc_swdev->swdev_rsel.si_note);
-               klist_invalidate(&sc->sc_swdev->swdev_wsel.si_note);
-               splx(s);
-
-               m_freem(sc->sc_swdev->swdev_lastm);
-               m_freem(sc->sc_swdev->swdev_inputm);
-               mq_purge(&sc->sc_swdev->swdev_outq);
-               free(sc->sc_swdev, M_DEVBUF, sizeof(struct switch_dev));
-               sc->sc_swdev = NULL;
-       }
-       rw_exit_write(&switch_ifs_lk);
-}
-
-int
-switchpoll(dev_t dev, int events, struct proc *p)
-{
-       int                      revents = 0;
-       struct switch_softc     *sc = switch_dev2sc(dev);
-
-       if (sc == NULL)
-               return (POLLERR);
-
-       if (events & (POLLIN | POLLRDNORM)) {
-               if (!mq_empty(&sc->sc_swdev->swdev_outq) ||
-                   sc->sc_swdev->swdev_lastm != NULL)
-                       revents |= events & (POLLIN | POLLRDNORM);
-       }
-       if (events & (POLLOUT | POLLWRNORM))
-               revents |= events & (POLLOUT | POLLWRNORM);
-       if (revents == 0) {
-               if (events & (POLLIN | POLLRDNORM))
-                       selrecord(p, &sc->sc_swdev->swdev_rsel);
-       }
-
-       return (revents);
-}
-
-int
-switchkqfilter(dev_t dev, struct knote *kn)
-{
-       struct switch_softc     *sc = switch_dev2sc(dev);
-       struct klist            *klist;
-
-       if (sc == NULL)
-               return (ENXIO);
-
-       switch (kn->kn_filter) {
-       case EVFILT_READ:
-               klist = &sc->sc_swdev->swdev_rsel.si_note;
-               kn->kn_fop = &switch_rd_filtops;
-               break;
-       case EVFILT_WRITE:
-               klist = &sc->sc_swdev->swdev_wsel.si_note;
-               kn->kn_fop = &switch_wr_filtops;
-               break;
-       default:
-               return (EINVAL);
-       }
-
-       kn->kn_hook = (caddr_t)sc;
-
-       klist_insert_locked(klist, kn);
-
-       return (0);
-}
-
-void
-filt_switch_rdetach(struct knote *kn)
-{
-       struct switch_softc     *sc = (struct switch_softc *)kn->kn_hook;
-       struct klist            *klist = &sc->sc_swdev->swdev_rsel.si_note;
-
-       klist_remove_locked(klist, kn);
-}
-
-int
-filt_switch_read(struct knote *kn, long hint)
-{
-       struct switch_softc     *sc = (struct switch_softc *)kn->kn_hook;
-
-       if (!mq_empty(&sc->sc_swdev->swdev_outq) ||
-           sc->sc_swdev->swdev_lastm != NULL) {
-               kn->kn_data = mq_len(&sc->sc_swdev->swdev_outq) +
-                   (sc->sc_swdev->swdev_lastm != NULL);
-               return (1);
-       }
-
-       return (0);
-}
-
-void
-filt_switch_wdetach(struct knote *kn)
-{
-       struct switch_softc     *sc = (struct switch_softc *)kn->kn_hook;
-       struct klist            *klist = &sc->sc_swdev->swdev_wsel.si_note;
-
-       klist_remove_locked(klist, kn);
-}
-
-int
-filt_switch_write(struct knote *kn, long hint)
-{
-       /* Always writable */
-       return (1);
-}
-
-int
-switch_dev_output(struct switch_softc *sc, struct mbuf *m)
-{
-       if (mq_enqueue(&sc->sc_swdev->swdev_outq, m) != 0)
-               return (-1);
-       switch_dev_wakeup(sc);
-
-       return (0);
-}
-
-void
-switch_dev_wakeup(struct switch_softc *sc)
-{
-       if (sc->sc_swdev->swdev_waiting) {
-               sc->sc_swdev->swdev_waiting = 0;
-               wakeup((caddr_t)sc);
-       }
-       selwakeup(&sc->sc_swdev->swdev_rsel);
-}
diff --git a/sys/net/switchofp.c b/sys/net/switchofp.c
deleted file mode 100644 (file)
index 9077d5d..0000000
+++ /dev/null
@@ -1,6671 +0,0 @@
-/*     $OpenBSD: switchofp.c,v 1.80 2021/03/10 10:21:48 jsg Exp $      */
-
-/*
- * Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
- * Copyright (c) 2015, 2016 YASUOKA Masahiko <yasuoka@openbsd.org>
- * Copyright (c) 2015, 2016 Reyk Floeter <reyk@openbsd.org>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "bpfilter.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/errno.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/selinfo.h>
-#include <sys/stdint.h>
-#include <sys/time.h>
-#include <sys/pool.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <netinet/in.h>
-#include <netinet/ip.h>
-#include <netinet/ip6.h>
-#include <netinet/udp.h>
-#include <netinet/tcp.h>
-#include <netinet/ip_icmp.h>
-#include <netinet/icmp6.h>
-#include <netinet6/nd6.h>
-#include <netinet/if_ether.h>
-#include <net/if_bridge.h>
-#include <net/if_switch.h>
-#include <net/if_vlan_var.h>
-#include <net/ofp.h>
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
-/*
- * Per-frame debugging can be done at any time using the BPF
- * hook of DLT_OPENFLOW (eg. tcpdump -y openflow -i switch0)
- */
-#ifdef DEBUG
-#define DPRINTF(__sc, ...)                             \
-do {                                                   \
-       struct switch_softc *_sc = __sc;                \
-       log(LOG_DEBUG, "%s: ", _sc->sc_if.if_xname);    \
-       addlog(__VA_ARGS__);                            \
-} while(/*CONSTCOND*/0)
-#else
-#define DPRINTF(__sc, ...)     do {} while(0)
-#endif
-
-struct swofp_flow_entry {
-       uint64_t                                 swfe_cookie;
-       uint16_t                                 swfe_priority;
-       uint8_t                                  swfe_table_id;
-       struct ofp_match                        *swfe_match;
-       LIST_ENTRY(swofp_flow_entry)             swfe_next;
-       uint64_t                                 swfe_packet_cnt;
-       uint64_t                                 swfe_byte_cnt;
-       struct ofp_instruction_goto_table       *swfe_goto_table;
-       struct ofp_instruction_write_metadata   *swfe_write_metadata;
-       struct ofp_instruction_actions          *swfe_write_actions;
-       struct ofp_instruction_actions          *swfe_apply_actions;
-       struct ofp_instruction_actions          *swfe_clear_actions;
-       struct ofp_instruction_meter            *swfe_meter;
-       struct ofp_instruction_experimenter     *swfe_experimenter;
-       struct timespec                          swfe_installed_time;
-       struct timespec                          swfe_idle_time;
-       uint16_t                                 swfe_idle_timeout;
-       uint16_t                                 swfe_hard_timeout;
-       uint16_t                                 swfe_flags;
-       int                                      swfe_tablemiss;
-};
-
-struct swofp_flow_table {
-       uint32_t                         swft_table_id;
-       TAILQ_ENTRY(swofp_flow_table)    swft_table_next;
-       uint64_t                         swft_lookup_count;
-       uint64_t                         swft_matched_count;
-       LIST_HEAD(, swofp_flow_entry)    swft_flow_list;
-       uint32_t                         swft_flow_num;
-};
-
-struct swofp_group_entry {
-       uint32_t                         swge_group_id;
-       LIST_ENTRY(swofp_group_entry)    swge_next;
-       uint64_t                         swge_packet_count;
-       uint64_t                         swge_byte_count;
-       uint32_t                         swge_ref_count;
-       uint8_t                          swge_type;
-       uint32_t                         swge_buckets_len;
-       struct ofp_bucket               *swge_buckets;
-       struct ofp_bucket_counter       *swge_bucket_counter; /* XXX */
-       struct timespec                  swge_installed_time;
-};
-
-struct swofp_action_set {
-       uint16_t                         swas_type;
-       struct ofp_action_header        *swas_action;
-};
-
-/* Same as total number of OFP_ACTION_ */
-#define SWOFP_ACTION_SET_MAX           18
-struct swofp_pipeline_desc {
-       uint32_t                         swpld_table_id;
-       uint64_t                         swpld_cookie;
-       uint64_t                         swpld_metadata;
-       struct switch_flow_classify     *swpld_swfcl;
-       struct switch_flow_classify      swpld_pre_swfcl;
-       struct switch_fwdp_queue         swpld_fwdp_q;
-       struct swofp_action_set          swpld_action_set[SWOFP_ACTION_SET_MAX];
-       struct ofp_action_header        *swpld_set_fields[OFP_XM_T_MAX];
-       int                              swpld_tablemiss;
-};
-
-struct swofp_ofs {
-       /* There are parameters by OpenFlow */
-       uint32_t                         swofs_xidnxt;
-       uint64_t                         swofs_datapath_id;
-       struct ofp_switch_config         swofs_switch_config;
-       struct timeout                   swofs_flow_timeout;
-       uint32_t                         swofs_flow_max_entry;
-       TAILQ_HEAD(, swofp_flow_table)   swofs_table_list;
-       uint32_t                         swofs_group_max_table;
-       int                              swofs_group_table_num;
-       LIST_HEAD(, swofp_group_entry)   swofs_group_table;
-       int                             (*swofp_cp_init)(struct switch_softc *);
-};
-
-struct swofp_mpmsg {
-       struct mbuf             *swmp_hdr;
-       struct mbuf_list         swmp_body;
-};
-#define SWOFP_MPMSG_MAX                0xffef
-
-typedef int    (*ofp_msg_handler)(struct switch_softc *, struct mbuf *);
-
-void    swofp_forward_ofs(struct switch_softc *, struct switch_flow_classify *,
-           struct mbuf *);
-
-int     swofp_input(struct switch_softc *, struct mbuf *);
-int     swofp_output(struct switch_softc *, struct mbuf *);
-void    swofp_timer(void *);
-
-struct ofp_oxm_class
-       *swofp_lookup_oxm_handler(struct ofp_ox_match *);
-ofp_msg_handler
-       swofp_lookup_msg_handler(uint8_t);
-ofp_msg_handler
-       swofp_lookup_mpmsg_handler(uint16_t);
-struct ofp_action_handler
-       *swofp_lookup_action_handler(uint16_t);
-ofp_msg_handler
-       *swofp_flow_mod_lookup_handler(uint8_t);
-struct swofp_pipeline_desc
-       *swofp_pipeline_desc_create(struct switch_flow_classify *);
-void    swofp_pipeline_desc_destroy(struct swofp_pipeline_desc *);
-int     swofp_flow_match_by_swfcl(struct ofp_match *,
-           struct switch_flow_classify *);
-struct swofp_flow_entry
-       *swofp_flow_lookup(struct swofp_flow_table *,
-           struct switch_flow_classify *);
-
-/*
- * Flow table
- */
-struct swofp_flow_table
-       *swofp_flow_table_lookup(struct switch_softc *, uint16_t);
-struct swofp_flow_table
-       *swofp_flow_table_add(struct switch_softc *, uint16_t);
-int     swofp_flow_table_delete(struct switch_softc *, uint16_t);
-void    swofp_flow_table_delete_all(struct switch_softc *);
-void    swofp_flow_delete_on_table_by_group(struct switch_softc *,
-           struct swofp_flow_table *, uint32_t);
-void    swofp_flow_delete_on_table(struct switch_softc *,
-           struct swofp_flow_table *, struct ofp_match *, uint16_t,
-           uint64_t, uint64_t cookie_mask, uint32_t,
-           uint32_t, int);
-
-/*
- * Group table
- */
-struct swofp_group_entry
-       *swofp_group_entry_lookup(struct switch_softc *, uint32_t);
-int     swofp_group_entry_add(struct switch_softc *,
-           struct swofp_group_entry *);
-int     swofp_group_entry_delete(struct switch_softc *,
-           struct swofp_group_entry *);
-int     swofp_group_entry_delete_all(struct switch_softc *);
-int     swofp_validate_buckets(struct switch_softc *, struct mbuf *, uint8_t,
-           uint16_t *, uint16_t *);
-
-/*
- * Flow entry
- */
-int     swofp_flow_entry_put_instructions(struct switch_softc *,
-           struct mbuf *, struct swofp_flow_entry *, uint16_t *, uint16_t *);
-void    swofp_flow_entry_table_free(struct ofp_instruction **);
-void    swofp_flow_entry_instruction_free(struct swofp_flow_entry *);
-void    swofp_flow_entry_free(struct swofp_flow_entry **);
-void    swofp_flow_entry_add(struct switch_softc *, struct swofp_flow_table *,
-           struct swofp_flow_entry *);
-void    swofp_flow_entry_delete(struct switch_softc *,
-           struct swofp_flow_table *, struct swofp_flow_entry *, uint8_t);
-int     swofp_flow_mod_cmd_common_modify(struct switch_softc *,
-           struct mbuf *, int );
-int     swofp_flow_cmp_non_strict(struct swofp_flow_entry *,
-           struct ofp_match *);
-int     swofp_flow_cmp_strict(struct swofp_flow_entry *, struct ofp_match *,
-           uint32_t);
-int     swofp_flow_cmp_common(struct swofp_flow_entry *,
-           struct ofp_match *, int);
-struct swofp_flow_entry
-       *swofp_flow_search_by_table(struct swofp_flow_table *,
-           struct ofp_match *, uint16_t);
-int     swofp_flow_has_group(struct ofp_instruction_actions *, uint32_t);
-int     swofp_flow_filter_out_port(struct ofp_instruction_actions *,
-           uint32_t);
-int     swofp_flow_filter(struct swofp_flow_entry *, uint64_t, uint64_t,
-           uint32_t, uint32_t);
-void    swofp_flow_timeout(struct switch_softc *);
-int     swofp_validate_oxm(struct ofp_ox_match *, uint16_t *);
-int     swofp_validate_flow_match(struct ofp_match *, uint16_t *);
-int     swofp_validate_flow_instruction(struct switch_softc *,
-           struct ofp_instruction *, size_t, uint16_t *, uint16_t *);
-int     swofp_validate_action(struct switch_softc *sc,
-           struct ofp_action_header *, size_t, uint16_t *);
-
-/*
- * OpenFlow protocol compare oxm
- */
-int    swofp_ox_cmp_data(struct ofp_ox_match *,
-           struct ofp_ox_match *, int);
-int    swofp_ox_cmp_ipv6_addr(struct ofp_ox_match *,
-           struct ofp_ox_match *, int);
-int    swofp_ox_cmp_ipv4_addr(struct ofp_ox_match *,
-           struct ofp_ox_match *, int);
-int    swofp_ox_cmp_vlan_vid(struct ofp_ox_match *,
-           struct ofp_ox_match *, int);
-int    swofp_ox_cmp_ether_addr(struct ofp_ox_match *,
-           struct ofp_ox_match *, int);
-/*
- * OpenFlow protocol match field handlers
- */
-int     swofp_ox_match_ether_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_vlan_vid(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_ipv6_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_ipv4_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_uint8(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_uint16(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_uint32(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_match_uint64(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-
-void    swofp_ox_match_put_start(struct ofp_match *);
-int     swofp_ox_match_put_end(struct ofp_match *);
-int     swofp_ox_match_put_uint32(struct ofp_match *, uint8_t, uint32_t);
-int     swofp_ox_match_put_uint64(struct ofp_match *, uint8_t, uint64_t);
-int     swofp_nx_match_put(struct ofp_match *, uint8_t, int, caddr_t);
-
-/*
- * OpenFlow protocol push/pop tag action handlers
- */
-struct mbuf
-       *swofp_action_push_vlan(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_action_pop_vlan(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_expand_8021q_tag(struct mbuf *);
-
-/*
- * OpenFlow protocol set field action handlers
- */
-struct mbuf
-       *swofp_apply_set_field_udp(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_tcp(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_nd6(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_icmpv6(struct mbuf *m, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_icmpv4(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_ipv6(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_ipv4(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_arp(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_ether(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field_tunnel(struct mbuf *, int,
-           struct switch_flow_classify *, struct switch_flow_classify *);
-struct mbuf
-       *swofp_apply_set_field(struct mbuf *, struct swofp_pipeline_desc *);
-int     swofp_ox_set_vlan_vid(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_uint8(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_uint16(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_uint32(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_uint64(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_ether_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_ipv4_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-int     swofp_ox_set_ipv6_addr(struct switch_flow_classify *,
-           struct ofp_ox_match *);
-
-/*
- * OpenFlow protocol execute action handlers
- */
-int     swofp_action_output_controller(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, uint16_t, uint8_t);
-struct mbuf
-       *swofp_action_output(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_action_group_all(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct swofp_group_entry *);
-struct mbuf
-       *swofp_action_group(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_action_set_field(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_execute_action(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_execute_action_set_field(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-struct mbuf
-       *swofp_execute_action_set(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *);
-struct mbuf
-       *swofp_apply_actions(struct switch_softc *, struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_instruction_actions *);
-struct swofp_action_set
-       *swofp_lookup_action_set(struct swofp_pipeline_desc *, uint16_t);
-void    swofp_write_actions_set_field(struct swofp_action_set *,
-           struct ofp_action_header *);
-int     swofp_write_actions(struct ofp_instruction_actions *,
-           struct swofp_pipeline_desc *);
-void    swofp_clear_actions_set_field(struct swofp_action_set *,
-           struct ofp_action_header *);
-int     swofp_clear_actions(struct ofp_instruction_actions *,
-           struct swofp_pipeline_desc *);
-void    swofp_write_metadata(struct ofp_instruction_write_metadata *,
-           struct swofp_pipeline_desc *);
-
-/*
- * OpenFlow protocol message handlers
- */
-void    swofp_send_hello(struct switch_softc *);
-int     swofp_recv_hello(struct switch_softc *, struct mbuf *);
-int     swofp_send_echo(struct switch_softc *, struct mbuf *);
-int     swofp_recv_echo(struct switch_softc *, struct mbuf *);
-void    swofp_send_error(struct switch_softc *, struct mbuf *,
-           uint16_t, uint16_t);
-int     swofp_recv_features_req(struct switch_softc *, struct mbuf *);
-int     swofp_recv_config_req(struct switch_softc *, struct mbuf *);
-int     swofp_recv_set_config(struct switch_softc *, struct mbuf *);
-int     swofp_send_flow_removed(struct switch_softc *,
-           struct swofp_flow_entry *, uint8_t);
-int     swofp_recv_packet_out(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod_cmd_add(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod_cmd_common_modify(struct switch_softc *,
-           struct mbuf *, int);
-int     swofp_flow_mod_cmd_modify(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod_cmd_modify_strict(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod_cmd_common_delete(struct switch_softc *,
-           struct mbuf *, int);
-int     swofp_flow_mod_cmd_delete(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod_cmd_delete_strict(struct switch_softc *, struct mbuf *);
-int     swofp_flow_mod(struct switch_softc *, struct mbuf *);
-int     swofp_group_mod_add(struct switch_softc *, struct mbuf *);
-int     swofp_group_mod_modify(struct switch_softc *, struct mbuf *);
-int     swofp_group_mod_delete(struct switch_softc *, struct mbuf *);
-int     swofp_group_mod(struct switch_softc *, struct mbuf *);
-int     swofp_multipart_req(struct switch_softc *, struct mbuf *);
-int     swofp_barrier_req(struct switch_softc *, struct mbuf *);
-void    swofp_barrier_reply(struct switch_softc *, struct mbuf *);
-
-/*
- * OpenFlow protocol multipart message handlers
- */
-int    swofp_mpmsg_reply_create(struct ofp_multipart *, struct swofp_mpmsg *);
-int    swofp_mpmsg_put(struct swofp_mpmsg *, caddr_t, size_t);
-int    swofp_mpmsg_m_put(struct swofp_mpmsg *, struct mbuf *);
-void   swofp_mpmsg_destroy(struct swofp_mpmsg *);
-int    swofp_multipart_reply(struct switch_softc *, struct swofp_mpmsg *);
-
-int    swofp_put_flow(struct mbuf *, struct swofp_flow_table *,
-           struct swofp_flow_entry *);
-int    swofp_put_flows_from_table(struct swofp_mpmsg *,
-           struct swofp_flow_table *, struct ofp_flow_stats_request *);
-void   swofp_aggregate_stat_from_table(struct ofp_aggregate_stats *,
-           struct swofp_flow_table *, struct ofp_aggregate_stats_request *);
-int    swofp_table_features_put_oxm(struct mbuf *, int *, uint16_t);
-int    swofp_table_features_put_actions(struct mbuf *, int *, uint16_t);
-int    swofp_table_features_put_instruction(struct mbuf *, int *, uint16_t);
-
-int    swofp_mp_recv_desc(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_flow(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_aggregate_flow_stat(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_table_stats(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_table_features(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_port_stats(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_port_desc(struct switch_softc *, struct mbuf *);
-int    swofp_mp_recv_group_desc(struct switch_softc *, struct mbuf *);
-
-/*
- * OXM (OpenFlow Extensible Match) structures appear in ofp_match structure
- * and ofp_instruction_{apply|write}_action structure.
- */
-#define OFP_OXM_FOREACH(hdr, len, curr)                                        \
-for ((curr) = (struct ofp_ox_match *)((caddr_t)(hdr) + sizeof(*hdr));  \
-     (caddr_t)(curr) < ((caddr_t)(hdr) + (len));                       \
-     (curr) = (struct ofp_ox_match *)((caddr_t)(curr) +                        \
-        (curr)->oxm_length + sizeof(*curr)))
-
-#define OFP_OXM_TERMINATED(hdr, len, curr)             \
-       (((caddr_t)(hdr) + (len)) <= (caddr_t)(curr))
-
-
-#define OFP_ACTION_FOREACH(head, len, curr)                            \
-/* struct ofp_action_header head, curr */                              \
-for ((curr) = (head); (caddr_t)curr < ((caddr_t)head + (len));         \
-    (curr) = (struct ofp_action_header *)((caddr_t)curr +              \
-       ntohs((curr)->ah_len)))
-
-/*
- * Get instruction offset in ofp_flow_mod
- */
-#define OFP_FLOW_MOD_MSG_INSTRUCTION_OFFSET(ofm)               \
-       (offsetof(struct ofp_flow_mod, fm_match) +              \
-           OFP_ALIGN(ntohs((ofm)->fm_match.om_length)))
-
-/*
- * Instructions "FOREACH" in ofp_flow_mod. You can get header using
- * OFP_FLOW_MOD_MSG_INSTRUCTION_PTR macro
- */
-#define OFP_FLOW_MOD_INSTRUCTON_FOREACH(hadr, end, curr)                       \
-for ((curr) = (head); (caddr_t)curr < ((caddr_t)head + (end));                 \
-     (curr) = (struct ofp_instruction *)((caddr_t)(curr) + (curr)->i_len))
-
-
-#define OFP_I_ACTIONS_FOREACH(head, curr)                                      \
-/* struct ofp_match head, struct ofp_ox_match curr */                          \
-for ((curr) = (struct ofp_action_header *)((caddr_t)head + sizeof(*head));     \
-    (caddr_t)curr < ((caddr_t)head + ntohs((head)->ia_len));                   \
-    (curr) = (struct ofp_action_header *)((caddr_t)curr +                      \
-        ntohs((curr)->ah_len)))
-
-#define OFP_BUCKETS_FOREACH(head, end, curr)                                   \
-for ((curr) = (head); (caddr_t)curr < ((caddr_t)head + (end));                 \
-     (curr) = (struct ofp_bucket *)((caddr_t)(curr) + ntohs((curr)->b_len)))
-
-
-/*
- * OpenFlow protocol message handlers
- */
-struct ofp_msg_class {
-       uint8_t         msg_type;
-       ofp_msg_handler msg_handler;
-};
-struct ofp_msg_class ofp_msg_table[] = {
-       { OFP_T_HELLO,                          swofp_recv_hello },
-       { OFP_T_ERROR,                          NULL /* unsupported */ },
-       { OFP_T_ECHO_REQUEST,                   swofp_recv_echo },
-       { OFP_T_ECHO_REPLY,                     NULL /* from switch */ },
-       { OFP_T_EXPERIMENTER,                   NULL /* unsupported */ },
-       { OFP_T_FEATURES_REQUEST,               swofp_recv_features_req },
-       { OFP_T_FEATURES_REPLY,                 NULL /* from switch */ },
-       { OFP_T_GET_CONFIG_REQUEST,             swofp_recv_config_req },
-       { OFP_T_GET_CONFIG_REPLY,               NULL /* from switch */ },
-       { OFP_T_SET_CONFIG,                     swofp_recv_set_config },
-       { OFP_T_PACKET_IN,                      NULL /* from switch */ },
-       { OFP_T_FLOW_REMOVED,                   NULL /* from switch */ },
-       { OFP_T_PORT_STATUS,                    NULL /* from switch */ },
-       { OFP_T_PACKET_OUT,                     swofp_recv_packet_out },
-       { OFP_T_FLOW_MOD,                       swofp_flow_mod },
-       { OFP_T_GROUP_MOD,                      swofp_group_mod },
-       { OFP_T_PORT_MOD,                       NULL /* unsupported */ },
-       { OFP_T_TABLE_MOD,                      NULL /* unsupported */ },
-       { OFP_T_MULTIPART_REQUEST,              swofp_multipart_req },
-       { OFP_T_MULTIPART_REPLY,                NULL /* from switch */ },
-       { OFP_T_BARRIER_REQUEST,                swofp_barrier_req },
-       { OFP_T_BARRIER_REPLY,                  NULL /* from switch */ },
-       { OFP_T_QUEUE_GET_CONFIG_REQUEST,       NULL /* unsupported */ },
-       { OFP_T_QUEUE_GET_CONFIG_REPLY,         NULL /* from switch */ },
-       { OFP_T_ROLE_REQUEST,                   NULL /* unsupported */ },
-       { OFP_T_ROLE_REPLY,                     NULL /* from switch */ },
-       { OFP_T_GET_ASYNC_REQUEST,              NULL /* unsupported */ },
-       { OFP_T_GET_ASYNC_REPLY,                NULL /* from switch */ },
-       { OFP_T_SET_ASYNC,                      NULL /* unsupported */ },
-       { OFP_T_METER_MOD,                      NULL /* unsupported */ }
-};
-
-
-/*
-* OpenFlow protocol modification flow message command handlers
-*/
-struct ofp_flow_mod_class {
-       uint8_t          ofm_cmd_type;
-       ofp_msg_handler  ofm_cmd_handler;
-};
-struct ofp_flow_mod_class ofp_flow_mod_table[] = {
-       { OFP_FLOWCMD_ADD,              swofp_flow_mod_cmd_add },
-       { OFP_FLOWCMD_MODIFY,           swofp_flow_mod_cmd_modify },
-       { OFP_FLOWCMD_MODIFY_STRICT,    swofp_flow_mod_cmd_modify_strict },
-       { OFP_FLOWCMD_DELETE,           swofp_flow_mod_cmd_delete },
-       { OFP_FLOWCMD_DELETE_STRICT,    swofp_flow_mod_cmd_delete_strict },
-};
-
-/*
- * OpenFlow protocol multipart handlers
- */
-struct ofp_mpmsg_class {
-       uint8_t          msgsg_type;
-       ofp_msg_handler  mpmsg_handler;
-};
-struct ofp_mpmsg_class ofp_mpmsg_table[] = {
-       { OFP_MP_T_DESC,                swofp_mp_recv_desc },
-       { OFP_MP_T_FLOW,                swofp_mp_recv_flow },
-       { OFP_MP_T_AGGREGATE,           swofp_mp_recv_aggregate_flow_stat },
-       { OFP_MP_T_TABLE,               swofp_mp_recv_table_stats },
-       { OFP_MP_T_PORT_STATS,          swofp_mp_recv_port_stats },
-       { OFP_MP_T_QUEUE,               NULL },
-       { OFP_MP_T_GROUP,               NULL },
-       { OFP_MP_T_GROUP_DESC,          swofp_mp_recv_group_desc },
-       { OFP_MP_T_GROUP_FEATURES,      NULL },
-       { OFP_MP_T_METER,               NULL },
-       { OFP_MP_T_METER_CONFIG,        NULL },
-       { OFP_MP_T_METER_FEATURES,      NULL },
-       { OFP_MP_T_TABLE_FEATURES,      swofp_mp_recv_table_features },
-       { OFP_MP_T_PORT_DESC,           swofp_mp_recv_port_desc }
-};
-
-/*
- * OpenFlow OXM match handlers
- */
-#define SWOFP_MATCH_MASK       0x1
-#define SWOFP_MATCH_WILDCARD   0x2
-
-struct ofp_oxm_class {
-       uint8_t  oxm_field;
-       uint8_t  oxm_len; /* This length defined by specification */
-       uint8_t  oxm_flags;
-       int     (*oxm_match)(struct switch_flow_classify *,
-                   struct ofp_ox_match *);
-       int     (*oxm_set)(struct switch_flow_classify *,
-                   struct ofp_ox_match *);
-       int     (*oxm_cmp)(struct ofp_ox_match *,
-                   struct ofp_ox_match *, int);
-};
-
-/*
- * Handlers for basic class for OpenFlow
- */
-struct ofp_oxm_class ofp_oxm_handlers[] = {
-       {
-               OFP_XM_T_IN_PORT,
-               sizeof(uint32_t),
-               0,
-               swofp_ox_match_uint32,          NULL,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IN_PHY_PORT,
-               sizeof(uint32_t),
-               0,
-               NULL,                           NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_META,
-               sizeof(uint64_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint64,  NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_ETH_DST,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-       {
-               OFP_XM_T_ETH_SRC,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-       {
-               OFP_XM_T_ETH_TYPE,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_VLAN_VID,
-               sizeof(uint16_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_vlan_vid,        swofp_ox_set_vlan_vid,
-               swofp_ox_cmp_vlan_vid
-       },
-       {
-               OFP_XM_T_VLAN_PCP,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IP_DSCP,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IP_ECN,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IP_PROTO,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IPV4_SRC,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-       {
-               OFP_XM_T_IPV4_DST,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-       {
-               OFP_XM_T_TCP_SRC,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_TCP_DST,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_UDP_SRC,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_UDP_DST,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_SCTP_SRC,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_SCTP_DST,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ICMPV4_TYPE,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ICMPV4_CODE,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ARP_OP,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint16,          swofp_ox_set_uint16,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ARP_SPA,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-       {
-               OFP_XM_T_ARP_TPA,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-       {
-               OFP_XM_T_ARP_SHA,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-       {
-               OFP_XM_T_ARP_THA,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-#ifdef INET6
-       {
-               OFP_XM_T_IPV6_SRC,
-               sizeof(struct in6_addr),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv6_addr,       swofp_ox_set_ipv6_addr,
-               swofp_ox_cmp_ipv6_addr
-       },
-       {
-               OFP_XM_T_IPV6_DST,
-               sizeof(struct in6_addr),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv6_addr,       swofp_ox_set_ipv6_addr,
-               swofp_ox_cmp_ipv6_addr
-       },
-       {
-               OFP_XM_T_IPV6_FLABEL,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint32,          swofp_ox_set_uint32,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ICMPV6_TYPE,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_ICMPV6_CODE,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint8,           swofp_ox_set_uint8,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IPV6_ND_TARGET,
-               sizeof(struct in6_addr),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv6_addr,       swofp_ox_set_ipv6_addr,
-               swofp_ox_cmp_ipv6_addr
-       },
-       {
-               OFP_XM_T_IPV6_ND_SLL,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-       {
-               OFP_XM_T_IPV6_ND_TLL,
-               ETHER_ADDR_LEN,
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ether_addr,      swofp_ox_set_ether_addr,
-               swofp_ox_cmp_ether_addr
-       },
-#endif /* INET6 */
-       {
-               OFP_XM_T_MPLS_LABEL,
-               sizeof(uint32_t),
-               SWOFP_MATCH_WILDCARD,
-               NULL,                           NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_MPLS_TC,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               NULL,                           NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_MPLS_BOS,
-               sizeof(uint8_t),
-               SWOFP_MATCH_WILDCARD,
-               NULL,                           NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_PBB_ISID,
-               3,
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               NULL,                           NULL,
-               NULL
-       },
-       {
-               OFP_XM_T_TUNNEL_ID,
-               sizeof(uint64_t),
-               SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint64,          swofp_ox_set_uint64,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_T_IPV6_EXTHDR,
-               sizeof(uint16_t),
-               SWOFP_MATCH_WILDCARD,
-               NULL,                           NULL,
-               NULL
-       },
-};
-
-/*
- * Handlers for backward compatibility with NXM
- */
-struct ofp_oxm_class ofp_oxm_nxm_handlers[] = {
-       {
-               OFP_XM_NXMT_TUNNEL_ID,
-               sizeof(uint64_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_uint64,          swofp_ox_set_uint64,
-               swofp_ox_cmp_data
-       },
-       {
-               OFP_XM_NXMT_TUNNEL_IPV4_SRC,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-       {
-               OFP_XM_NXMT_TUNNEL_IPV4_DST,
-               sizeof(uint32_t),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv4_addr,       swofp_ox_set_ipv4_addr,
-               swofp_ox_cmp_ipv4_addr
-       },
-#ifdef INET6
-       {
-               OFP_XM_NXMT_TUNNEL_IPV6_SRC,
-               sizeof(struct in6_addr),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv6_addr,       swofp_ox_set_ipv6_addr,
-               swofp_ox_cmp_ipv6_addr
-       },
-       {
-               OFP_XM_NXMT_TUNNEL_IPV6_DST,
-               sizeof(struct in6_addr),
-               SWOFP_MATCH_MASK|SWOFP_MATCH_WILDCARD,
-               swofp_ox_match_ipv6_addr,       swofp_ox_set_ipv6_addr,
-               swofp_ox_cmp_ipv6_addr
-       },
-#endif /* INET6 */
-};
-
-/*
- * OpenFlow action handlers
- */
-struct ofp_action_handler {
-       uint16_t         action_type;
-       struct mbuf *   (*action)(struct switch_softc *,  struct mbuf *,
-           struct swofp_pipeline_desc *, struct ofp_action_header *);
-};
-struct ofp_action_handler ofp_action_handlers[] = {
-       /*
-        * Following order complies with action set order in
-        * OpenFlow Switch Specification (ver. 1.3.5)
-        */
-       {
-               OFP_ACTION_COPY_TTL_IN,
-               NULL
-       },
-       {
-               OFP_ACTION_POP_MPLS,
-               NULL
-       },
-       {
-               OFP_ACTION_POP_PBB,
-               NULL
-       },
-       {
-               OFP_ACTION_POP_VLAN,
-               swofp_action_pop_vlan
-       },
-       {
-               OFP_ACTION_PUSH_MPLS,
-               NULL
-       },
-       {
-               OFP_ACTION_PUSH_PBB,
-               NULL
-       },
-       {
-               OFP_ACTION_PUSH_VLAN,
-               swofp_action_push_vlan
-       },
-       {
-               OFP_ACTION_COPY_TTL_OUT,
-               NULL
-       },
-       {
-               OFP_ACTION_DEC_NW_TTL,
-               NULL
-       },
-       {
-               OFP_ACTION_DEC_MPLS_TTL,
-               NULL
-       },
-       {
-               OFP_ACTION_SET_MPLS_TTL,
-               NULL
-       },
-       {
-               OFP_ACTION_SET_NW_TTL,
-               NULL
-       },
-       {
-               OFP_ACTION_SET_FIELD,
-               swofp_action_set_field
-       },
-       {
-               OFP_ACTION_SET_QUEUE,
-               NULL
-       },
-       {
-               OFP_ACTION_GROUP,
-               swofp_action_group
-       },
-       {
-               OFP_ACTION_OUTPUT,
-               swofp_action_output
-       },
-       {
-               OFP_ACTION_EXPERIMENTER,
-               NULL
-       }, /* XXX Where is best position? */
-};
-
-extern struct pool swfcl_pool;
-struct pool swpld_pool;
-
-void
-swofp_attach(void)
-{
-       pool_init(&swpld_pool, sizeof(struct swofp_pipeline_desc), 0, 0, 0,
-           "swpld", NULL);
-}
-
-
-int
-swofp_create(struct switch_softc *sc)
-{
-       struct swofp_ofs        *swofs;
-       int                      error;
-
-       swofs = malloc(sizeof(*swofs), M_DEVBUF, M_NOWAIT|M_ZERO);
-       if (swofs == NULL)
-               return (ENOMEM);
-
-       sc->sc_ofs = swofs;
-
-       TAILQ_INIT(&swofs->swofs_table_list);
-
-       /*
-        * A table with id 0 must exist
-        */
-       if ((swofp_flow_table_add(sc, 0)) == NULL) {
-               error = ENOBUFS;
-               free(swofs, M_DEVBUF, sizeof(*swofs));
-               return (error);
-       }
-
-       swofs->swofs_xidnxt = 1;
-       arc4random_buf(&swofs->swofs_datapath_id,
-           sizeof(swofs->swofs_datapath_id));
-
-       timeout_set(&swofs->swofs_flow_timeout, swofp_timer, sc);
-       timeout_add_sec(&swofs->swofs_flow_timeout, 10);
-
-       /* TODO: Configured from ifconfig  */
-       swofs->swofs_group_max_table = 1000;
-       swofs->swofs_flow_max_entry = 10000;
-
-       sc->sc_capabilities |= SWITCH_CAP_OFP;
-       sc->switch_process_forward = swofp_forward_ofs;
-
-#if NBPFILTER > 0
-       bpfattach(&sc->sc_ofbpf, &sc->sc_if, DLT_OPENFLOW,
-           sizeof(struct ofp_header));
-#endif
-
-       return (0);
-}
-
-void
-swofp_destroy(struct switch_softc *sc)
-{
-       struct swofp_ofs        *swofs = sc->sc_ofs;
-
-       if ((sc->sc_capabilities & SWITCH_CAP_OFP) == 0 || swofs == NULL)
-               return;
-
-       timeout_del(&swofs->swofs_flow_timeout);
-
-       sc->sc_capabilities &= ~SWITCH_CAP_OFP;
-       sc->switch_process_forward = NULL;
-
-       swofp_group_entry_delete_all(sc);
-
-       free(swofs, M_DEVBUF, sizeof(*swofs));
-}
-
-int
-swofp_init(struct switch_softc *sc)
-{
-       sc->sc_swdev->swdev_input = swofp_input;
-       swofp_send_hello(sc);
-       return (0);
-}
-
-uint32_t
-swofp_assign_portno(struct switch_softc *sc, uint32_t req)
-{
-       struct switch_port      *swpo;
-       uint32_t                 candidate;
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-               if (swpo->swpo_port_no == req)
-                       break;
-       }
-       if (swpo == NULL)
-               return (req);
-
-       /* XXX
-        * OS's ifindex is "short", so it expect that floowing is unique
-        */
-       candidate = (req << 16) | req;
-       while (1) {
-               TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if (swpo->swpo_port_no == candidate)
-                               break;
-               }
-               if (swpo == NULL)
-                       return (candidate);
-
-               if (candidate < OFP_PORT_MAX)
-                       candidate++;
-               else
-                       candidate = 0;
-       }
-}
-
-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)
-                       break;
-               memcpy(&swofs->swofs_datapath_id, &bparam->ifbrp_datapath,
-                   sizeof(uint64_t));
-               break;
-       case SIOCSWGMAXFLOW:
-               bparam->ifbrp_maxflow = swofs->swofs_flow_max_entry;
-               break;
-       case SIOCSWGMAXGROUP:
-               bparam->ifbrp_maxgroup = swofs->swofs_group_max_table;
-               break;
-       case SIOCSWSPORTNO:
-               if ((error = suser(curproc)) != 0)
-                       break;
-
-               if (breq->ifbr_portno >= OFP_PORT_MAX)
-                       return (EINVAL);
-
-               if ((ifs = if_unit(breq->ifbr_ifsname)) == NULL)
-                       return (ENOENT);
-
-               if (ifs->if_switchport == NULL) {
-                       if_put(ifs);
-                       return (ENOENT);
-               }
-
-               TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if (swpo->swpo_port_no == breq->ifbr_portno) {
-                               if_put(ifs);
-                               return (EEXIST);
-                       }
-               }
-
-               swpo = (struct switch_port *)ifs->if_switchport;
-               if_put(ifs);
-               swpo->swpo_port_no = breq->ifbr_portno;
-
-               break;
-       default:
-               error = ENOTTY;
-               break;
-       }
-
-       return (error);
-}
-
-/* TODO: Optimization */
-struct ofp_oxm_class *
-swofp_lookup_oxm_handler(struct ofp_ox_match *oxm)
-{
-       struct ofp_oxm_class    *handlers;
-       uint8_t                  oxm_field;
-       int                      i, len;
-
-       switch (ntohs(oxm->oxm_class)) {
-       case OFP_OXM_C_OPENFLOW_BASIC:
-               handlers = ofp_oxm_handlers;
-               len = nitems(ofp_oxm_handlers);
-               break;
-       case OFP_OXM_C_NXM_1:
-               handlers = ofp_oxm_nxm_handlers;
-               len = nitems(ofp_oxm_nxm_handlers);
-               break;
-       default:
-               return (NULL);
-       }
-
-       oxm_field = OFP_OXM_GET_FIELD(oxm);
-
-       for (i = 0; i < len ; i++) {
-               if (handlers[i].oxm_field == oxm_field)
-                       return (&handlers[i]);
-       }
-
-       return (NULL);
-}
-
-ofp_msg_handler
-swofp_lookup_msg_handler(uint8_t type)
-{
-       if (type >= OFP_T_TYPE_MAX)
-               return (NULL);
-       else
-               return (ofp_msg_table[type].msg_handler);
-}
-
-ofp_msg_handler
-swofp_lookup_mpmsg_handler(uint16_t type)
-{
-       if (type >= nitems(ofp_mpmsg_table))
-               return (NULL);
-       else
-               return (ofp_mpmsg_table[type].mpmsg_handler);
-}
-
-struct ofp_action_handler *
-swofp_lookup_action_handler(uint16_t type)
-{
-       int     i;
-
-       for (i = 0; i < nitems(ofp_action_handlers); i++) {
-               if (ofp_action_handlers[i].action_type == type)
-                       return &(ofp_action_handlers[i]);
-       }
-
-       return (NULL);
-}
-
-struct swofp_pipeline_desc *
-swofp_pipeline_desc_create(struct switch_flow_classify *swfcl)
-{
-       struct swofp_pipeline_desc      *swpld = NULL;
-       struct swofp_action_set         *swas = NULL;
-       int                              i;
-
-       swpld = pool_get(&swpld_pool, PR_NOWAIT|PR_ZERO);
-       if (swpld == NULL)
-               return (NULL);
-
-       /*
-        * ofp_action_handlers is sorted by applying action-set order,
-        * so it can be used for initializer for action-set.
-        */
-       swas = swpld->swpld_action_set;
-       for (i = 0; i < nitems(ofp_action_handlers); i++) {
-               swas[i].swas_type = ofp_action_handlers[i].action_type;
-               if (swas[i].swas_type == OFP_ACTION_SET_FIELD)
-                       swas[i].swas_action = (struct ofp_action_header *)
-                           swpld->swpld_set_fields;
-               else
-                       swas[i].swas_action = NULL;
-       }
-
-       swpld->swpld_swfcl = swfcl;
-
-       return (swpld);
-}
-
-void
-swofp_pipeline_desc_destroy(struct swofp_pipeline_desc *swpld)
-{
-       switch_swfcl_free(&swpld->swpld_pre_swfcl);
-       pool_put(&swpld_pool, swpld);
-}
-
-struct swofp_flow_table *
-swofp_flow_table_lookup(struct switch_softc *sc, uint16_t table_id)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft;
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if (swft->swft_table_id == table_id)
-                       return (swft);
-       }
-
-       return (NULL);
-}
-
-struct swofp_flow_table *
-swofp_flow_table_add(struct switch_softc *sc, uint16_t table_id)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft, *new;
-
-       if ((swft = swofp_flow_table_lookup(sc, table_id)) != NULL)
-               return (swft);
-
-       if ((new = malloc(sizeof(*new), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL)
-               return (NULL);
-
-       new->swft_table_id = table_id;
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if (table_id < swft->swft_table_id)
-                       break;
-       }
-
-       if (swft)
-               TAILQ_INSERT_BEFORE(swft, new, swft_table_next);
-       else
-               TAILQ_INSERT_TAIL(&ofs->swofs_table_list, new, swft_table_next);
-
-       DPRINTF(sc, "add openflow flow table (id:%d)\n", table_id);
-
-       return (new);
-}
-
-int
-swofp_flow_table_delete(struct switch_softc *sc, uint16_t table_id)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft;
-       struct swofp_flow_entry *swfe, *tswfe;
-
-       if ((swft = swofp_flow_table_lookup(sc, table_id)) == NULL)
-               return ENOENT;
-
-       LIST_FOREACH_SAFE(swfe, &swft->swft_flow_list, swfe_next, tswfe) {
-               /*
-                * Flows are deleted force because of deleting table,
-                * s it's not necessary to send flow remove message.
-                */
-               swfe->swfe_flags &= ~(OFP_FLOWFLAG_SEND_FLOW_REMOVED);
-               swofp_flow_entry_delete(sc, swft, swfe,
-                   OFP_FLOWREM_REASON_DELETE);
-       }
-
-       TAILQ_REMOVE(&ofs->swofs_table_list, swft, swft_table_next);
-       free(swft, M_DEVBUF, sizeof(*swft));
-
-       DPRINTF(sc, "delete flow table (id:%d)\n", table_id);
-
-       return 0;
-}
-
-void
-swofp_flow_table_delete_all(struct switch_softc *sc)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft, *tswft;
-       int                      error;
-
-       TAILQ_FOREACH_SAFE(swft, &ofs->swofs_table_list,
-           swft_table_next, tswft) {
-               if ((error = swofp_flow_table_delete(sc,swft->swft_table_id)))
-                       log(LOG_ERR, "can't delete table id:%d (error:%d)\n",
-                           swft->swft_table_id, error);
-       }
-}
-
-struct swofp_group_entry *
-swofp_group_entry_lookup(struct switch_softc *sc, uint32_t group_id)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct swofp_group_entry        *swge;
-
-       LIST_FOREACH(swge, &ofs->swofs_group_table, swge_next) {
-               if (swge->swge_group_id == group_id)
-                       return swge;
-       }
-
-       return (NULL);
-}
-
-int
-swofp_group_entry_add(struct switch_softc *sc, struct swofp_group_entry *swge)
-{
-       struct swofp_ofs *ofs = sc->sc_ofs;
-
-       LIST_INSERT_HEAD(&ofs->swofs_group_table, swge, swge_next);
-       ofs->swofs_group_table_num++;
-
-       DPRINTF(sc, "add group %d in group table (total %d)\n",
-           swge->swge_group_id, ofs->swofs_group_table_num);
-
-       return (0);
-}
-
-int
-swofp_group_entry_delete(struct switch_softc *sc,
-    struct swofp_group_entry *swge)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft;
-
-       DPRINTF(sc, "delete group %d in group table (total %d)\n",
-           swge->swge_group_id, ofs->swofs_group_table_num);
-
-       LIST_REMOVE(swge, swge_next);
-       ofs->swofs_group_table_num--;
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               swofp_flow_delete_on_table_by_group(sc, swft,
-                   swge->swge_group_id);
-       }
-
-       free(swge->swge_buckets, M_DEVBUF, swge->swge_buckets_len);
-       free(swge, M_DEVBUF, sizeof(*swge));
-
-       return (0);
-}
-
-int
-swofp_group_entry_delete_all(struct switch_softc *sc)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct swofp_group_entry        *swge, *tswge;
-
-       LIST_FOREACH_SAFE(swge, &ofs->swofs_group_table, swge_next, tswge) {
-               swofp_group_entry_delete(sc, swge);
-       }
-
-       return (0);
-}
-
-int
-swofp_validate_buckets(struct switch_softc *sc, struct mbuf *m, uint8_t type,
-    uint16_t *etype, uint16_t *error)
-{
-       struct ofp_group_mod    *ogm;
-       struct ofp_bucket       *bucket;
-       struct ofp_action_header *ah;
-       uint16_t                weight, remaining;
-       int                     start, len, off, num;
-       size_t                  blen;
-
-       *etype = OFP_ERRTYPE_GROUP_MOD_FAILED;
-
-       ogm = mtod(m, struct ofp_group_mod *);
-       start = offsetof(struct ofp_group_mod, gm_buckets);
-       remaining = len = ntohs(ogm->gm_oh.oh_length) - start;
-
-       /* Invalid packet size. */
-       if (len < 0) {
-               *error = OFP_ERRGROUPMOD_INVALID_GROUP;
-               return (-1);
-       }
-
-       /* Indirect group type must always have one bucket. */
-       if (len < sizeof(*bucket) && type == OFP_GROUP_T_INDIRECT) {
-               *error = OFP_ERRGROUPMOD_INVALID_GROUP;
-               return (-1);
-       }
-
-       for (off = start, num = 0; off < start + len; off += blen, num++) {
-               bucket = (struct ofp_bucket *)(mtod(m, caddr_t) + off);
-
-               blen = ntohs(bucket->b_len);
-               if (blen < sizeof(*bucket)) {
-                       *error = OFP_ERRGROUPMOD_BAD_BUCKET;
-                       return (-1);
-               }
-
-               /* Validate that the bucket is smaller than the payload. */
-               if (blen > remaining) {
-                       *etype = OFP_ERRTYPE_BAD_REQUEST;
-                       *error = OFP_ERRREQ_BAD_LEN;
-                       return (-1);
-               }
-               remaining -= blen;
-
-               /*
-                * Validate weight
-                */
-               switch (type) {
-               case OFP_GROUP_T_ALL:
-               case OFP_GROUP_T_INDIRECT:
-               case OFP_GROUP_T_FAST_FAILOVER:
-                       if (ntohs(bucket->b_weight) != 0) {
-                               *error = OFP_ERRGROUPMOD_BAD_BUCKET;
-                               return (-1);
-                       }
-                       break;
-               case OFP_GROUP_T_SELECT:
-                       if (num > 1 && weight != ntohs(bucket->b_weight)) {
-                               *error = OFP_ERRGROUPMOD_WEIGHT_UNSUPP;
-                               return (-1);
-                       }
-                       break;
-               }
-
-               /*
-                * INDIRECT type has only one bucket
-                */
-               if (type == OFP_GROUP_T_INDIRECT && num > 1) {
-                       *error = OFP_ERRGROUPMOD_BAD_BUCKET;
-                       return (-1);
-               }
-
-               weight = ntohs(bucket->b_weight);
-
-               /* Skip if there are no actions to validate. */
-               if (blen == sizeof(*bucket))
-                       continue;
-
-               ah = (struct ofp_action_header *)
-                   (mtod(m, caddr_t) + off + sizeof(*bucket));
-               if (swofp_validate_action(sc, ah, blen - sizeof(*bucket),
-                   error)) {
-                       *etype = OFP_ERRTYPE_BAD_ACTION;
-                       return (-1);
-               }
-       }
-
-       return (0);
-}
-
-void
-swofp_flow_entry_table_free(struct ofp_instruction **table)
-{
-       if (*table) {
-               free(*table, M_DEVBUF, ntohs((*table)->i_len));
-               *table = NULL;
-       }
-}
-
-void
-swofp_flow_entry_instruction_free(struct swofp_flow_entry *swfe)
-{
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_goto_table);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_write_metadata);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_apply_actions);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_write_actions);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_clear_actions);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_experimenter);
-       swofp_flow_entry_table_free((struct ofp_instruction **)
-           &swfe->swfe_meter);
-}
-
-void
-swofp_flow_entry_free(struct swofp_flow_entry **swfe)
-{
-       if ((*swfe)->swfe_match)
-               free((*swfe)->swfe_match, M_DEVBUF,
-                   ntohs((*swfe)->swfe_match->om_length));
-
-       swofp_flow_entry_instruction_free(*swfe);
-
-       free((*swfe), M_DEVBUF, sizeof(**swfe));
-}
-
-void
-swofp_flow_entry_add(struct switch_softc *sc, struct swofp_flow_table *swft,
-    struct swofp_flow_entry *swfe)
-{
-       swfe->swfe_table_id = swft->swft_table_id;
-       LIST_INSERT_HEAD(&swft->swft_flow_list, swfe, swfe_next);
-       swft->swft_flow_num++;
-
-       DPRINTF(sc, "add flow in table %d (total %d)\n",
-           swft->swft_table_id, swft->swft_flow_num);
-}
-
-void
-swofp_flow_entry_delete(struct switch_softc *sc, struct swofp_flow_table *swft,
-    struct swofp_flow_entry *swfe, uint8_t reason)
-{
-       if (swfe->swfe_flags & OFP_FLOWFLAG_SEND_FLOW_REMOVED)
-               swofp_send_flow_removed(sc, swfe, reason);
-
-       LIST_REMOVE(swfe, swfe_next);
-       swofp_flow_entry_free(&swfe);
-       swft->swft_flow_num--;
-
-       DPRINTF(sc, "delete flow from table %d (total %d)\n",
-           swft->swft_table_id, swft->swft_flow_num);
-}
-
-void
-swofp_flow_timeout(struct switch_softc *sc)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct swofp_flow_table *swft;
-       struct swofp_flow_entry *swfe, *tswfe;
-       struct timespec          now, duration, idle;
-
-       nanouptime(&now);
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               LIST_FOREACH_SAFE(swfe, &swft->swft_flow_list,
-                   swfe_next, tswfe) {
-                       if (swfe->swfe_idle_timeout) {
-                               timespecsub(&now, &swfe->swfe_idle_time, &idle);
-                               if (swfe->swfe_idle_timeout < idle.tv_sec) {
-                                       DPRINTF(sc, "flow expired "
-                                           "by idle timeout\n");
-                                       swofp_flow_entry_delete(sc, swft, swfe,
-                                           OFP_FLOWREM_REASON_IDLE_TIMEOUT);
-                                       continue;
-                               }
-                       }
-                       if (swfe->swfe_hard_timeout) {
-                               timespecsub(&now, &swfe->swfe_installed_time,
-                                   &duration);
-                               if (swfe->swfe_hard_timeout < duration.tv_sec) {
-                                       DPRINTF(sc, "flow expired "
-                                           "by hard timeout\n");
-                                       swofp_flow_entry_delete(sc, swft, swfe,
-                                           OFP_FLOWREM_REASON_HARD_TIMEOUT);
-                               }
-                       }
-               }
-       }
-}
-
-void
-swofp_timer(void *v)
-{
-       struct switch_softc     *sc = (struct switch_softc *)v;
-       struct swofp_ofs        *swofs = sc->sc_ofs;
-
-       swofp_flow_timeout(sc);
-       timeout_add_sec(&swofs->swofs_flow_timeout, 10);
-}
-
-int
-swofp_ox_cmp_data(struct ofp_ox_match *target,
-    struct ofp_ox_match *key, int strict)
-{
-       uint64_t         tmth, tmask, kmth, kmask;
-       uint64_t         dummy_mask = UINT64_MAX;
-       int              len;
-
-       if (OFP_OXM_GET_FIELD(target) != OFP_OXM_GET_FIELD(key))
-               return (1);
-
-       switch (OFP_OXM_GET_FIELD(target)) {
-       case OFP_XM_T_VLAN_PCP:
-       case OFP_XM_T_IP_DSCP:
-       case OFP_XM_T_IP_ECN:
-       case OFP_XM_T_IP_PROTO:
-       case OFP_XM_T_ICMPV4_CODE:
-       case OFP_XM_T_ICMPV4_TYPE:
-       case OFP_XM_T_ICMPV6_CODE:
-       case OFP_XM_T_ICMPV6_TYPE:
-               len = sizeof(uint8_t);
-               break;
-       case OFP_XM_T_ETH_TYPE:
-       case OFP_XM_T_TCP_SRC:
-       case OFP_XM_T_TCP_DST:
-       case OFP_XM_T_UDP_SRC:
-       case OFP_XM_T_UDP_DST:
-       case OFP_XM_T_ARP_OP:
-               len = sizeof(uint16_t);
-               break;
-       case OFP_XM_T_IN_PORT:
-       case OFP_XM_T_IPV6_FLABEL:
-               len = sizeof(uint32_t);
-               break;
-       case OFP_XM_T_TUNNEL_ID: /* alias OFP_XM_NXMT_TUNNEL_ID */
-               len = sizeof(uint64_t);
-               break;
-       default:
-               return (1);
-       }
-
-       tmth = tmask = kmth = kmask = 0;
-
-       memcpy(&tmth, ((caddr_t)target + sizeof(*target)), len);
-       if (OFP_OXM_GET_HASMASK(target))
-               memcpy(&tmask, ((caddr_t)target + sizeof(*target) + len), len);
-       else
-               memcpy(&tmask, &dummy_mask, len);
-
-       memcpy(&kmth, ((caddr_t)key + sizeof(*key)), len);
-       if (OFP_OXM_GET_HASMASK(key))
-               memcpy(&kmask, ((caddr_t)key + sizeof(*key) + len), len);
-       else
-               memcpy(&kmask, &dummy_mask, len);
-
-       if (strict) {
-               if (tmask != kmask)
-                       return (1);
-       } else {
-               if ((tmask & kmask) != kmask)
-                       return (1);
-       }
-
-       return !((tmth & tmask) == (kmth & kmask));
-}
-
-#ifdef INET6
-int
-swofp_ox_cmp_ipv6_addr(struct ofp_ox_match *target,
-    struct ofp_ox_match *key, int strict)
-{
-       struct in6_addr tmth, tmask, kmth, kmask;
-       struct in6_addr mask = in6mask128;
-
-       if (OFP_OXM_GET_FIELD(target) != OFP_OXM_GET_FIELD(key))
-               return (1);
-
-       switch (OFP_OXM_GET_FIELD(target)) {
-       case OFP_XM_NXMT_TUNNEL_IPV6_SRC:
-       case OFP_XM_NXMT_TUNNEL_IPV6_DST:
-       case OFP_XM_T_IPV6_SRC:
-       case OFP_XM_T_IPV6_DST:
-       case OFP_XM_T_IPV6_ND_TARGET:
-               break;
-       default:
-               return (1);
-       }
-
-       memcpy(&kmth, ((caddr_t)key + sizeof(*key)), sizeof(kmth));
-       if (OFP_OXM_GET_HASMASK(key))
-               memcpy(&kmask, ((caddr_t)key + sizeof(*key) + sizeof(kmask)),
-                   sizeof(kmask));
-       else
-               kmask = mask;
-
-       memcpy(&tmth, ((caddr_t)target + sizeof(*target)), sizeof(tmth));
-       if (OFP_OXM_GET_HASMASK(target))
-               memcpy(&tmask, ((caddr_t)target + sizeof(*target) +
-                   sizeof(tmask)), sizeof(tmask));
-       else
-               tmask = mask;
-
-       if (strict) {
-               if (memcmp(&tmask, &kmask, sizeof(tmask)) != 0)
-                       return (1);
-
-               tmth.s6_addr32[0] &= tmask.s6_addr32[0];
-               tmth.s6_addr32[1] &= tmask.s6_addr32[1];
-               tmth.s6_addr32[2] &= tmask.s6_addr32[2];
-               tmth.s6_addr32[3] &= tmask.s6_addr32[3];
-
-               kmth.s6_addr32[0] &= kmask.s6_addr32[0];
-               kmth.s6_addr32[1] &= kmask.s6_addr32[1];
-               kmth.s6_addr32[2] &= kmask.s6_addr32[2];
-               kmth.s6_addr32[3] &= kmask.s6_addr32[3];
-
-       } else {
-               tmask.s6_addr32[0] &= kmask.s6_addr32[0];
-               tmask.s6_addr32[1] &= kmask.s6_addr32[1];
-               tmask.s6_addr32[2] &= kmask.s6_addr32[2];
-               tmask.s6_addr32[3] &= kmask.s6_addr32[3];
-
-               if (memcmp(&tmask, &kmask, sizeof(tmask)) != 0)
-                       return (1);
-
-               tmth.s6_addr32[0] &= kmask.s6_addr32[0];
-               tmth.s6_addr32[1] &= kmask.s6_addr32[1];
-               tmth.s6_addr32[2] &= kmask.s6_addr32[2];
-               tmth.s6_addr32[3] &= kmask.s6_addr32[3];
-
-               kmth.s6_addr32[0] &= kmask.s6_addr32[0];
-               kmth.s6_addr32[1] &= kmask.s6_addr32[1];
-               kmth.s6_addr32[2] &= kmask.s6_addr32[2];
-               kmth.s6_addr32[3] &= kmask.s6_addr32[3];
-
-       }
-
-       return memcmp(&tmth, &kmth, sizeof(tmth));
-}
-#endif /* INET6 */
-
-int
-swofp_ox_cmp_ipv4_addr(struct ofp_ox_match *target,
-    struct ofp_ox_match *key, int strict)
-{
-       uint32_t        tmth, tmask, kmth, kmask;
-
-       if (OFP_OXM_GET_FIELD(target) != OFP_OXM_GET_FIELD(key))
-               return (1);
-
-       switch (OFP_OXM_GET_FIELD(target)) {
-       case OFP_XM_NXMT_TUNNEL_IPV4_SRC:
-       case OFP_XM_NXMT_TUNNEL_IPV4_DST:
-       case OFP_XM_T_IPV4_SRC:
-       case OFP_XM_T_IPV4_DST:
-       case OFP_XM_T_ARP_SPA:
-       case OFP_XM_T_ARP_TPA:
-               break;
-       default:
-               return (1);
-       }
-
-       memcpy(&tmth, ((caddr_t)target + sizeof(*target)), sizeof(uint32_t));
-       if (OFP_OXM_GET_HASMASK(target))
-               memcpy(&tmask, ((caddr_t)target + sizeof(*target) +
-                   sizeof(uint32_t)), sizeof(uint32_t));
-       else
-               tmask = UINT32_MAX;
-
-       memcpy(&kmth, ((caddr_t)key + sizeof(*key)), sizeof(uint32_t));
-       if (OFP_OXM_GET_HASMASK(key))
-               memcpy(&kmask, ((caddr_t)key + sizeof(*key) +
-                   sizeof(uint32_t)), sizeof(uint32_t));
-       else
-               kmask = UINT32_MAX;
-
-       if (strict) {
-               if (tmask != kmask)
-                       return (1);
-       } else {
-               if ((tmask & kmask) != kmask)
-                       return (1);
-       }
-
-       return !((tmth & kmask) == (kmth & kmask));
-}
-
-int
-swofp_ox_cmp_vlan_vid(struct ofp_ox_match *target,
-    struct ofp_ox_match *key, int strict)
-{
-       uint16_t tmth, tmask, kmth, kmask;
-
-       if (OFP_OXM_GET_FIELD(target) != OFP_OXM_GET_FIELD(key) ||
-           OFP_OXM_GET_FIELD(target) != OFP_XM_T_VLAN_VID)
-               return (1);
-
-       memcpy(&tmth, ((caddr_t)target + sizeof(*target)), sizeof(uint16_t));
-       if (OFP_OXM_GET_HASMASK(target))
-               memcpy(&tmask, ((caddr_t)target + sizeof(*target)
-                   + sizeof(uint16_t)), sizeof(uint16_t));
-       else
-               tmask = UINT16_MAX;
-
-       memcpy(&kmth, ((caddr_t)key + sizeof(*key)), sizeof(uint16_t));
-       if (OFP_OXM_GET_HASMASK(key))
-               memcpy(&kmask, ((caddr_t)key + sizeof(*key) +
-                   sizeof(uint16_t)), sizeof(uint16_t));
-       else
-               kmask = UINT16_MAX;
-
-       tmth &= htons(EVL_VLID_MASK);
-       tmask &= htons(EVL_VLID_MASK);
-       kmth &= htons(EVL_VLID_MASK);
-       kmask &= htons(EVL_VLID_MASK);
-
-       if (strict) {
-               if (tmask != kmask)
-                       return (1);
-       } else {
-               if ((tmask & kmask) != kmask)
-                       return (1);
-       }
-
-       return !((tmth & kmask) == (kmth & kmask));
-}
-
-int
-swofp_ox_cmp_ether_addr(struct ofp_ox_match *target,
-    struct ofp_ox_match *key, int strict)
-{
-       uint64_t         tmth, tmask, kmth, kmask;
-       uint64_t         eth_mask = 0x0000FFFFFFFFFFFFULL;
-
-
-       if (OFP_OXM_GET_FIELD(target) != OFP_OXM_GET_FIELD(key))
-               return (1);
-
-       switch (OFP_OXM_GET_FIELD(target)) {
-       case OFP_XM_T_ETH_SRC:
-       case OFP_XM_T_ETH_DST:
-       case OFP_XM_T_ARP_SHA:
-       case OFP_XM_T_ARP_THA:
-       case OFP_XM_T_IPV6_ND_SLL:
-       case OFP_XM_T_IPV6_ND_TLL:
-               break;
-       default:
-               return (1);
-       }
-
-       memcpy(&tmth, ((caddr_t)target + sizeof(*target)), ETHER_ADDR_LEN);
-       if (OFP_OXM_GET_HASMASK(target))
-               memcpy(&tmask, ((caddr_t)target + sizeof(*target) +
-                   ETHER_ADDR_LEN), ETHER_ADDR_LEN);
-       else
-               tmask = UINT64_MAX;
-
-       memcpy(&kmth, ((caddr_t)key + sizeof(*key)), ETHER_ADDR_LEN);
-       if (OFP_OXM_GET_HASMASK(key))
-               memcpy(&kmask, ((caddr_t)key + sizeof(*key) +
-                   ETHER_ADDR_LEN), ETHER_ADDR_LEN);
-       else
-               kmask = UINT64_MAX;
-
-       tmask &= eth_mask;
-       tmth &= eth_mask;
-       kmask &= eth_mask;
-       kmth &= eth_mask;
-
-       if (strict) {
-               if (tmask != kmask)
-                       return (1);
-       } else {
-               if ((tmask & kmask) != kmask)
-                       return (1);
-       }
-
-       return !((tmth & kmask) == (kmth & kmask));
-}
-
-int
-swofp_validate_oxm(struct ofp_ox_match *oxm, uint16_t *err)
-{
-       struct ofp_oxm_class    *handler;
-       int                      hasmask;
-       int                      neededlen;
-
-       handler = swofp_lookup_oxm_handler(oxm);
-       if (handler == NULL || handler->oxm_match == NULL) {
-               *err = OFP_ERRMATCH_BAD_FIELD;
-               return (-1);
-       }
-
-       hasmask = OFP_OXM_GET_HASMASK(oxm);
-
-       neededlen = (hasmask) ?
-           (handler->oxm_len * 2) : (handler->oxm_len);
-       if (oxm->oxm_length != neededlen) {
-               *err = OFP_ERRMATCH_BAD_LEN;
-               return (-1);
-       }
-
-       return (0);
-}
-
-int
-swofp_validate_flow_match(struct ofp_match *om, uint16_t *err)
-{
-       struct ofp_ox_match *oxm;
-
-       /*
-        * TODO this function is missing checks for:
-        * - OFP_ERRMATCH_BAD_TAG;
-        * - OFP_ERRMATCH_BAD_VALUE;
-        * - OFP_ERRMATCH_BAD_MASK;
-        * - OFP_ERRMATCH_BAD_PREREQ;
-        * - OFP_ERRMATCH_DUP_FIELD;
-        */
-       OFP_OXM_FOREACH(om, ntohs(om->om_length), oxm) {
-               if (swofp_validate_oxm(oxm, err))
-                       return (*err);
-       }
-
-       return (0);
-}
-
-int
-swofp_validate_flow_instruction(struct switch_softc *sc,
-    struct ofp_instruction *oi, size_t total, uint16_t *etype,
-    uint16_t *err)
-{
-       struct ofp_action_header        *oah;
-       struct ofp_instruction_actions  *oia;
-       int                              ilen;
-
-       *etype = OFP_ERRTYPE_BAD_INSTRUCTION;
-
-       ilen = ntohs(oi->i_len);
-       /* Check for bigger than packet or smaller than header. */
-       if (ilen > total || ilen < sizeof(*oi)) {
-               *err = OFP_ERRINST_BAD_LEN;
-               return (-1);
-       }
-
-       switch (ntohs(oi->i_type)) {
-       case OFP_INSTRUCTION_T_GOTO_TABLE:
-               if (ilen != sizeof(struct ofp_instruction_goto_table)) {
-                       *err = OFP_ERRINST_BAD_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_INSTRUCTION_T_WRITE_META:
-               if (ilen != sizeof(struct ofp_instruction_write_metadata)) {
-                       *err = OFP_ERRINST_BAD_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_INSTRUCTION_T_METER:
-               if (ilen != sizeof(struct ofp_instruction_meter)) {
-                       *err = OFP_ERRINST_BAD_LEN;
-                       return (-1);
-               }
-               break;
-
-       case OFP_INSTRUCTION_T_WRITE_ACTIONS:
-       case OFP_INSTRUCTION_T_CLEAR_ACTIONS:
-       case OFP_INSTRUCTION_T_APPLY_ACTIONS:
-               if (ilen < sizeof(*oia)) {
-                       *err = OFP_ERRINST_BAD_LEN;
-                       return (-1);
-               }
-
-               oia = (struct ofp_instruction_actions *)oi;
-
-               /* Validate actions before iterating over them. */
-               oah = (struct ofp_action_header *)
-                   ((uint8_t *)oia + sizeof(*oia));
-               if (swofp_validate_action(sc, oah, ilen - sizeof(*oia),
-                   err)) {
-                       *etype = OFP_ERRTYPE_BAD_ACTION;
-                       return (-1);
-               }
-               break;
-
-       case OFP_INSTRUCTION_T_EXPERIMENTER:
-               /* FALLTHROUGH */
-       default:
-               *err = OFP_ERRINST_UNKNOWN_INST;
-               return (-1);
-       }
-
-       return (0);
-}
-
-int
-swofp_validate_action(struct switch_softc *sc, struct ofp_action_header *ah,
-    size_t ahtotal, uint16_t *err)
-{
-       struct ofp_action_handler       *oah;
-       struct ofp_ox_match             *oxm;
-       struct ofp_action_push          *ap;
-       struct ofp_action_group         *ag;
-       struct ofp_action_output        *ao;
-       struct switch_port              *swpo;
-       uint8_t                         *dptr;
-       int                              ahtype, ahlen, oxmlen;
-
-       /* No actions. */
-       if (ahtotal == 0)
-               return (0);
-
-       /* Check if we have at least the first header. */
-       if (ahtotal < sizeof(*ah)) {
-               *err = OFP_ERRACTION_LEN;
-               return (-1);
-       }
-
- parse_next_action:
-       ahtype = ntohs(ah->ah_type);
-       ahlen = ntohs(ah->ah_len);
-       if (ahlen < sizeof(*ah) || ahlen > ahtotal) {
-               *err = OFP_ERRACTION_LEN;
-               return (-1);
-       }
-
-       switch (ahtype) {
-       case OFP_ACTION_OUTPUT:
-               if (ahlen != sizeof(struct ofp_action_output)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-
-               ao = (struct ofp_action_output *)ah;
-               switch (ntohl(ao->ao_port)) {
-               case OFP_PORT_ANY:
-                       *err = OFP_ERRACTION_OUT_PORT;
-                       return (-1);
-
-               case OFP_PORT_ALL:
-               case OFP_PORT_NORMAL:
-                       /* TODO implement port ALL and NORMAL. */
-                       *err = OFP_ERRACTION_OUT_PORT;
-                       return (-1);
-
-               case OFP_PORT_CONTROLLER:
-               case OFP_PORT_FLOWTABLE:
-               case OFP_PORT_FLOOD:
-               case OFP_PORT_INPUT:
-               case OFP_PORT_LOCAL:
-                       break;
-
-               default:
-                       TAILQ_FOREACH(swpo, &sc->sc_swpo_list,
-                           swpo_list_next) {
-                               if (swpo->swpo_port_no ==
-                                   ntohl(ao->ao_port))
-                                       break;
-                       }
-                       if (swpo == NULL) {
-                               *err = OFP_ERRACTION_OUT_PORT;
-                               return (-1);
-                       }
-                       break;
-               }
-               break;
-       case OFP_ACTION_GROUP:
-               if (ahlen != sizeof(struct ofp_action_group)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-
-               ag = (struct ofp_action_group *)ah;
-               if (swofp_group_entry_lookup(sc,
-                   ntohl(ag->ag_group_id)) == NULL) {
-                       *err = OFP_ERRACTION_BAD_OUT_GROUP;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_SET_QUEUE:
-               if (ahlen != sizeof(struct ofp_action_set_queue)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_SET_MPLS_TTL:
-               if (ahlen != sizeof(struct ofp_action_mpls_ttl)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_SET_NW_TTL:
-               if (ahlen != sizeof(struct ofp_action_nw_ttl)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_COPY_TTL_OUT:
-       case OFP_ACTION_COPY_TTL_IN:
-       case OFP_ACTION_DEC_MPLS_TTL:
-       case OFP_ACTION_POP_VLAN:
-               if (ahlen != sizeof(struct ofp_action_header)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_PUSH_VLAN:
-       case OFP_ACTION_PUSH_MPLS:
-       case OFP_ACTION_PUSH_PBB:
-               if (ahlen != sizeof(struct ofp_action_push)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-
-               ap = (struct ofp_action_push *)ah;
-               switch (ntohs(ap->ap_type)) {
-               case OFP_ACTION_PUSH_VLAN:
-                       if (ntohs(ap->ap_ethertype) != ETHERTYPE_VLAN &&
-                           ntohs(ap->ap_ethertype) != ETHERTYPE_QINQ) {
-                               *err = OFP_ERRACTION_ARGUMENT;
-                               return (-1);
-                       }
-                       break;
-
-               case OFP_ACTION_PUSH_MPLS:
-               case OFP_ACTION_PUSH_PBB:
-                       /* Not implemented yet. */
-               default:
-                       *err = OFP_ERRACTION_TYPE;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_POP_MPLS:
-               if (ahlen != sizeof(struct ofp_action_pop_mpls)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-               break;
-       case OFP_ACTION_SET_FIELD:
-               if (ahlen < sizeof(struct ofp_action_set_field) ||
-                   ahlen != OFP_ALIGN(ahlen)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-
-               oxmlen = ahlen - (sizeof(struct ofp_action_set_field) -
-                   offsetof(struct ofp_action_set_field, asf_field));
-               if (oxmlen < sizeof(*oxm)) {
-                       *err = OFP_ERRACTION_LEN;
-                       return (-1);
-               }
-
-               dptr = (uint8_t *)ah;
-               dptr += sizeof(struct ofp_action_set_field) -
-                   offsetof(struct ofp_action_set_field, asf_field);
-               oxm = (struct ofp_ox_match *)dptr;
-               oxmlen -= sizeof(struct ofp_ox_match);
-               if (oxmlen < oxm->oxm_length) {
-                       *err = OFP_ERRACTION_SET_LEN;
-                       return (-1);
-               }
-               /* Remainder is padding. */
-               oxmlen -= oxm->oxm_length;
-               if (oxmlen >= OFP_ALIGNMENT) {
-                       *err = OFP_ERRACTION_SET_LEN;
-                       return (-1);
-               }
-
-               if (swofp_validate_oxm(oxm, err)) {
-                       if (*err == OFP_ERRMATCH_BAD_LEN)
-                               *err = OFP_ERRACTION_SET_LEN;
-                       else
-                               *err = OFP_ERRACTION_SET_TYPE;
-                       return (-1);
-               }
-
-               dptr += sizeof(struct ofp_ox_match) + oxm->oxm_length;
-               while (oxmlen > 0) {
-                       if (*dptr != 0) {
-                               *err = OFP_ERRACTION_SET_ARGUMENT;
-                               return (-1);
-                       }
-                       oxmlen--;
-                       dptr++;
-               }
-               break;
-       default:
-               /* Unknown/unsupported action. */
-               *err = OFP_ERRACTION_TYPE;
-               return (-1);
-       }
-
-       oah = swofp_lookup_action_handler(ahtype);
-       /* Unknown/unsupported action. */
-       if (oah == NULL) {
-               *err = OFP_ERRACTION_TYPE;
-               return (-1);
-       }
-
-       ahtotal -= min(ahlen, ahtotal);
-       if (ahtotal) {
-               ah = (struct ofp_action_header *)((uint8_t *)ah + ahlen);
-               goto parse_next_action;
-       }
-
-       return (0);
-}
-
-int
-swofp_flow_filter_out_port(struct ofp_instruction_actions *oia,
-    uint32_t out_port)
-{
-       struct ofp_action_header        *oah;
-       struct ofp_action_output        *oao;
-
-       if (oia == NULL)
-               return (0);
-
-       OFP_I_ACTIONS_FOREACH((struct ofp_instruction_actions *)oia, oah) {
-               if (ntohs(oah->ah_type) == OFP_ACTION_OUTPUT) {
-                       oao = (struct ofp_action_output *)oah;
-                       if (ntohl(oao->ao_port) == out_port)
-                               return (1);
-               }
-       }
-
-       return (0);
-}
-
-int
-swofp_flow_filter(struct swofp_flow_entry *swfe, uint64_t cookie,
-    uint64_t cookie_mask, uint32_t out_port, uint32_t out_group)
-{
-
-       if (cookie_mask != 0 &&
-           ((swfe->swfe_cookie & cookie_mask) != (cookie & cookie_mask)))
-               return (0);
-
-       if ((out_port == OFP_PORT_ANY) && (out_group == OFP_GROUP_ID_ALL))
-               return (1);
-
-       if ((out_port != OFP_PORT_ANY) &&
-           !(swofp_flow_filter_out_port(swfe->swfe_write_actions, out_port) ||
-           swofp_flow_filter_out_port(swfe->swfe_apply_actions, out_port)))
-           return (0);
-
-       if (out_port != OFP_GROUP_ID_ALL) {
-               /* XXX ignore group */
-       }
-
-       return (1);
-}
-
-int
-swofp_flow_cmp_common(struct swofp_flow_entry *swfe, struct ofp_match *key,
-    int strict)
-{
-       struct ofp_match        *target = swfe->swfe_match;
-       struct ofp_oxm_class    *khandler;
-       struct ofp_ox_match     *toxm, *koxm;
-       void                    *kmask;
-       int                      len;
-       /* maximam payload size is size of struct in6_addr */
-       uint8_t                  dummy_unmask[sizeof(struct in6_addr)];
-
-       memset(dummy_unmask, 0, sizeof(dummy_unmask));
-
-       OFP_OXM_FOREACH(key, ntohs(key->om_length), koxm) {
-               khandler = swofp_lookup_oxm_handler(koxm);
-               if (khandler == NULL || khandler->oxm_match == NULL)
-                       return (0);
-
-               len = khandler->oxm_len;
-
-               /*
-                * OpenFlow Switch Specification 1.3.5 says:
-                *  - An all-zero-bits oxm_mask is equivalent to omitting
-                *    the OXM TLV entirely
-                */
-               if (strict && OFP_OXM_GET_HASMASK(koxm)) {
-                       kmask = (void *)((caddr_t)koxm + sizeof(*koxm) + len);
-                       if (memcmp(kmask, dummy_unmask, len) == 0)
-                               continue;
-               }
-
-               OFP_OXM_FOREACH(target, ntohs(target->om_length), toxm) {
-                       if (khandler->oxm_cmp(toxm, koxm, strict) == 0)
-                               break;
-               }
-               if (OFP_OXM_TERMINATED(target, ntohs(target->om_length), toxm))
-                       return (0);
-       }
-
-       return (1);
-}
-
-int
-swofp_flow_cmp_non_strict(struct swofp_flow_entry *swfe, struct ofp_match *key)
-{
-       /* Every oxm matching is wildcard */
-       if (key == NULL)
-               return (1);
-
-       return swofp_flow_cmp_common(swfe, key, 0);
-}
-
-int
-swofp_flow_cmp_strict(struct swofp_flow_entry *swfe, struct ofp_match *key,
-    uint32_t priority)
-{
-       struct ofp_match        *target = swfe->swfe_match;
-       struct ofp_ox_match     *toxm, *koxm;
-       int                      key_matches, target_matches;
-
-       /*
-        * Both target and key values are put on network byte order,
-        * so it's ok that those are compared without changing byte order
-        */
-       if (swfe->swfe_priority != priority)
-               return (0);
-
-       key_matches = target_matches = 0;
-       OFP_OXM_FOREACH(key, ntohs(key->om_length), koxm)
-               key_matches++;
-
-       OFP_OXM_FOREACH(target, ntohs(target->om_length), toxm)
-               target_matches++;
-
-       if (key_matches != target_matches)
-               return (0);
-
-       return swofp_flow_cmp_common(swfe, key, 1);
-}
-
-struct swofp_flow_entry *
-swofp_flow_search_by_table(struct swofp_flow_table *swft, struct ofp_match *key,
-    uint16_t priority)
-{
-       struct swofp_flow_entry *swfe;
-
-       LIST_FOREACH(swfe, &swft->swft_flow_list, swfe_next) {
-               if (swofp_flow_cmp_strict(swfe, key, priority))
-                       return (swfe);
-       }
-
-       return (NULL);
-}
-
-int
-swofp_flow_has_group(struct ofp_instruction_actions *oia, uint32_t group_id)
-{
-       struct ofp_action_header        *oah;
-       struct ofp_action_group         *oag;
-
-       if (oia == NULL)
-               return (0);
-
-       OFP_I_ACTIONS_FOREACH((struct ofp_instruction_actions *)oia, oah) {
-               if (ntohs(oah->ah_type) == OFP_ACTION_GROUP) {
-                       oag = (struct ofp_action_group *)oah;
-                       if (ntohl(oag->ag_group_id) == group_id)
-                               return (1);
-               }
-       }
-
-       return (0);
-}
-
-void
-swofp_flow_delete_on_table_by_group(struct switch_softc *sc,
-    struct swofp_flow_table *swft, uint32_t group_id)
-{
-       struct swofp_flow_entry *swfe, *tswfe;
-
-       LIST_FOREACH_SAFE(swfe, &swft->swft_flow_list, swfe_next, tswfe) {
-               if (swofp_flow_has_group(swfe->swfe_apply_actions, group_id) ||
-                   swofp_flow_has_group(swfe->swfe_write_actions, group_id)) {
-                       swofp_flow_entry_delete(sc, swft, swfe,
-                           OFP_FLOWREM_REASON_GROUP_DELETE);
-               }
-       }
-}
-
-void
-swofp_flow_delete_on_table(struct switch_softc *sc,
-    struct swofp_flow_table *swft, struct ofp_match *key, uint16_t priority,
-    uint64_t cookie, uint64_t cookie_mask, uint32_t out_port,
-    uint32_t out_group, int strict)
-{
-       struct swofp_flow_entry *swfe, *tswfe;
-
-       LIST_FOREACH_SAFE(swfe, &swft->swft_flow_list, swfe_next, tswfe) {
-               if (strict && !swofp_flow_cmp_strict(swfe, key, priority))
-                       continue;
-               else if (!swofp_flow_cmp_non_strict(swfe, key))
-                       continue;
-
-               if (!swofp_flow_filter(swfe, cookie, cookie_mask,
-                   out_port, out_group))
-                       continue;
-
-               swofp_flow_entry_delete(sc, swft, swfe,
-                   OFP_FLOWREM_REASON_DELETE);
-       }
-}
-
-void
-swofp_ox_match_put_start(struct ofp_match *om)
-{
-       om->om_type = htons(OFP_MATCH_OXM);
-       om->om_length = htons(sizeof(*om));
-}
-
-/*
- * Return ofp_match length include "PADDING" byte
- */
-int
-swofp_ox_match_put_end(struct ofp_match *om)
-{
-       int      tsize = ntohs(om->om_length);
-       int      padding;
-
-       padding = OFP_ALIGN(tsize) - tsize;
-       if (padding)
-               memset((caddr_t)om + tsize, 0, padding);
-
-       return tsize + padding;
-}
-
-int
-swofp_ox_match_put_uint32(struct ofp_match *om, uint8_t type, uint32_t val)
-{
-       int      off = ntohs(om->om_length);
-       struct ofp_ox_match *oxm;
-
-       val = htonl(val);
-       oxm = (struct ofp_ox_match *)((caddr_t)om + off);
-       oxm->oxm_class = htons(OFP_OXM_C_OPENFLOW_BASIC);
-       OFP_OXM_SET_FIELD(oxm, type);
-       oxm->oxm_length = sizeof(uint32_t);
-       memcpy(oxm->oxm_value, &val, sizeof(val));
-       om->om_length = htons(ntohs(om->om_length) +
-           sizeof(*oxm) + sizeof(uint32_t));
-
-       return ntohs(om->om_length);
-}
-
-int
-swofp_ox_match_put_uint64(struct ofp_match *om, uint8_t type, uint64_t val)
-{
-       struct ofp_ox_match     *oxm;
-       int                      off = ntohs(om->om_length);
-
-       val = htobe64(val);
-       oxm = (struct ofp_ox_match *)((caddr_t)om + off);
-       oxm->oxm_class = htons(OFP_OXM_C_OPENFLOW_BASIC);
-       OFP_OXM_SET_FIELD(oxm, type);
-       oxm->oxm_length = sizeof(uint64_t);
-       memcpy(oxm->oxm_value, &val, sizeof(val));
-       om->om_length = htons(ntohs(om->om_length) +
-           sizeof(*oxm) + sizeof(uint64_t));
-
-       return ntohs(om->om_length);
-}
-
-int
-swofp_nx_match_put(struct ofp_match *om, uint8_t type, int len,
-    caddr_t val)
-{
-       struct ofp_ox_match     *oxm;
-       int                      off = ntohs(om->om_length);
-
-       oxm = (struct ofp_ox_match *)((caddr_t)om + off);
-       oxm->oxm_class = htons(OFP_OXM_C_NXM_1);
-       OFP_OXM_SET_FIELD(oxm, type);
-       oxm->oxm_length = len;
-       memcpy((void *)oxm->oxm_value, val, len);
-
-       om->om_length = htons(ntohs(om->om_length) + sizeof(*oxm) + len);
-
-       return ntohs(om->om_length);
-}
-
-int
-swofp_ox_set_vlan_vid(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint16_t         val;
-
-       val = *(uint16_t *)oxm->oxm_value;
-       swfcl->swfcl_vlan->vlan_vid = (val & htons(EVL_VLID_MASK));
-
-       return (0);
-}
-
-int
-swofp_ox_set_uint8(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint8_t          val;
-
-       val = *(uint8_t *)oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_IP_DSCP:
-               if (swfcl->swfcl_ipv4)
-                       swfcl->swfcl_ipv4->ipv4_tos = ((val << 2) |
-                           (swfcl->swfcl_ipv4->ipv4_tos & IPTOS_ECN_MASK));
-               else
-                       swfcl->swfcl_ipv6->ipv6_tclass = ((val << 2) |
-                           (swfcl->swfcl_ipv6->ipv6_tclass & IPTOS_ECN_MASK));
-               break;
-       case OFP_XM_T_IP_ECN:
-               if (swfcl->swfcl_ipv4)
-                       swfcl->swfcl_ipv4->ipv4_tos = ((val & IPTOS_ECN_MASK) |
-                           (swfcl->swfcl_ipv4->ipv4_tos & ~IPTOS_ECN_MASK));
-               else
-                       swfcl->swfcl_ipv6->ipv6_tclass = (
-                           (val & IPTOS_ECN_MASK) |
-                           (swfcl->swfcl_ipv6->ipv6_tclass & ~IPTOS_ECN_MASK));
-               break;
-       case OFP_XM_T_IP_PROTO:
-               if (swfcl->swfcl_ipv4)
-                       swfcl->swfcl_ipv4->ipv4_proto = val;
-               else
-                       swfcl->swfcl_ipv6->ipv6_nxt = val;
-               break;
-       case OFP_XM_T_ICMPV4_TYPE:
-               swfcl->swfcl_icmpv4->icmpv4_type = val;
-               break;
-       case OFP_XM_T_ICMPV4_CODE:
-               swfcl->swfcl_icmpv4->icmpv4_code = val;
-               break;
-       case OFP_XM_T_ICMPV6_TYPE:
-               swfcl->swfcl_icmpv6->icmpv6_type = val;
-               break;
-       case OFP_XM_T_ICMPV6_CODE:
-               swfcl->swfcl_icmpv6->icmpv6_code = val;
-               break;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_uint16(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint16_t         val;
-
-       val = *(uint16_t *)oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_TYPE:
-               swfcl->swfcl_ether->eth_type = val;
-               break;
-       case OFP_XM_T_VLAN_PCP:
-               swfcl->swfcl_vlan->vlan_pcp = val;
-               break;
-       case OFP_XM_T_TCP_SRC:
-               swfcl->swfcl_tcp->tcp_src = val;
-               break;
-       case OFP_XM_T_TCP_DST:
-               swfcl->swfcl_tcp->tcp_dst = val;
-               break;
-       case OFP_XM_T_UDP_SRC:
-               swfcl->swfcl_udp->udp_src = val;
-               break;
-       case OFP_XM_T_UDP_DST:
-               swfcl->swfcl_udp->udp_dst = val;
-               break;
-       case OFP_XM_T_ARP_OP:
-               swfcl->swfcl_arp->_arp_op = val;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_uint32(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint32_t        val;
-
-       val = *(uint32_t *)oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_IPV6_FLABEL:
-               swfcl->swfcl_ipv6->ipv6_flow_label = val;
-               break;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_uint64(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint64_t         val;
-
-       val = *(uint64_t *)oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_TUNNEL_ID: /* alias OFP_XM_NXMT_TUNNEL_ID */
-               swfcl->swfcl_tunnel->tun_key = val;
-               break;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_ipv6_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       struct in6_addr  val;
-
-       memcpy(&val, oxm->oxm_value, sizeof(val));
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV6_SRC:
-               swfcl->swfcl_tunnel->tun_ipv6_src = val;
-               break;
-       case OFP_XM_NXMT_TUNNEL_IPV6_DST:
-               swfcl->swfcl_tunnel->tun_ipv6_dst = val;
-               break;
-       case OFP_XM_T_IPV6_SRC:
-               swfcl->swfcl_ipv6->ipv6_src = val;
-               break;
-       case OFP_XM_T_IPV6_DST:
-               swfcl->swfcl_ipv6->ipv6_dst = val;
-               break;
-       case OFP_XM_T_IPV6_ND_TARGET:
-               swfcl->swfcl_nd6->nd6_target = val;
-               break;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_ipv4_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint32_t         val;
-
-       val = *(uint32_t *)oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV4_SRC:
-               swfcl->swfcl_tunnel->tun_ipv4_src = *(struct in_addr *)&val;
-               break;
-       case OFP_XM_NXMT_TUNNEL_IPV4_DST:
-               swfcl->swfcl_tunnel->tun_ipv4_dst = *(struct in_addr *)&val;
-               break;
-       case OFP_XM_T_IPV4_SRC:
-               swfcl->swfcl_ipv4->ipv4_src = val;
-               break;
-       case OFP_XM_T_IPV4_DST:
-               swfcl->swfcl_ipv4->ipv4_dst = val;
-               break;
-       case OFP_XM_T_ARP_SPA:
-               swfcl->swfcl_arp->arp_sip = val;
-               break;
-       case OFP_XM_T_ARP_TPA:
-               swfcl->swfcl_arp->arp_tip = val;
-               break;
-       }
-
-       return (0);
-}
-
-int
-swofp_ox_set_ether_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       caddr_t         eth_addr;
-
-       eth_addr = oxm->oxm_value;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_SRC:
-               memcpy(swfcl->swfcl_ether->eth_src, eth_addr, ETHER_ADDR_LEN);
-               break;
-       case OFP_XM_T_ETH_DST:
-               memcpy(swfcl->swfcl_ether->eth_dst, eth_addr, ETHER_ADDR_LEN);
-               break;
-       case OFP_XM_T_ARP_SHA:
-               memcpy(swfcl->swfcl_arp->arp_sha, eth_addr, ETHER_ADDR_LEN);
-               break;
-       case OFP_XM_T_ARP_THA:
-               memcpy(swfcl->swfcl_arp->arp_tha, eth_addr, ETHER_ADDR_LEN);
-               break;
-       case OFP_XM_T_IPV6_ND_TLL:
-       case OFP_XM_T_IPV6_ND_SLL:
-               memcpy(swfcl->swfcl_nd6->nd6_lladdr, eth_addr, ETHER_ADDR_LEN);
-               break;
-       }
-
-       return (0);
-}
-
-#ifdef INET6
-int
-swofp_ox_match_ipv6_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       struct in6_addr  in, mth, mask = in6mask128;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV6_SRC:
-       case OFP_XM_NXMT_TUNNEL_IPV6_DST:
-               if (swfcl->swfcl_tunnel == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_IPV6_SRC:
-       case OFP_XM_T_IPV6_DST:
-               if (swfcl->swfcl_ipv6 == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_IPV6_ND_TARGET:
-               if (swfcl->swfcl_nd6 == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV6_SRC:
-               in = swfcl->swfcl_tunnel->tun_ipv6_src;
-               break;
-       case OFP_XM_NXMT_TUNNEL_IPV6_DST:
-               in = swfcl->swfcl_tunnel->tun_ipv6_dst;
-               break;
-       case OFP_XM_T_IPV6_SRC:
-               in = swfcl->swfcl_ipv6->ipv6_src;
-               break;
-       case OFP_XM_T_IPV6_DST:
-               in = swfcl->swfcl_ipv6->ipv6_dst;
-               break;
-       case OFP_XM_T_IPV6_ND_TARGET:
-               in = swfcl->swfcl_nd6->nd6_target;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(mth));
-
-       if (OFP_OXM_GET_HASMASK(oxm)) {
-               memcpy(&mask, oxm->oxm_value + sizeof(mth),
-                   sizeof(mask));
-
-               in.s6_addr32[0] &= mask.s6_addr32[0];
-               in.s6_addr32[1] &= mask.s6_addr32[1];
-               in.s6_addr32[2] &= mask.s6_addr32[2];
-               in.s6_addr32[3] &= mask.s6_addr32[3];
-
-               mth.s6_addr32[0] &= mask.s6_addr32[0];
-               mth.s6_addr32[1] &= mask.s6_addr32[1];
-               mth.s6_addr32[2] &= mask.s6_addr32[2];
-               mth.s6_addr32[3] &= mask.s6_addr32[3];
-       }
-
-       return memcmp(&in, &mth, sizeof(in));
-}
-#endif /* INET6 */
-
-int
-swofp_ox_match_ipv4_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint32_t         in, mth, mask;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV4_SRC:
-       case OFP_XM_NXMT_TUNNEL_IPV4_DST:
-               if (swfcl->swfcl_tunnel == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_IPV4_SRC:
-       case OFP_XM_T_IPV4_DST:
-               if (swfcl->swfcl_ipv4 == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_ARP_SPA:
-       case OFP_XM_T_ARP_TPA:
-               if (swfcl->swfcl_arp == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_NXMT_TUNNEL_IPV4_SRC:
-               in = swfcl->swfcl_tunnel->tun_ipv4_src.s_addr;
-               break;
-       case OFP_XM_NXMT_TUNNEL_IPV4_DST:
-               in = swfcl->swfcl_tunnel->tun_ipv4_dst.s_addr;
-               break;
-       case OFP_XM_T_IPV4_SRC:
-               in = swfcl->swfcl_ipv4->ipv4_src;
-               break;
-       case OFP_XM_T_IPV4_DST:
-               in = swfcl->swfcl_ipv4->ipv4_dst;
-               break;
-       case OFP_XM_T_ARP_SPA:
-               in = swfcl->swfcl_arp->arp_sip;
-               break;
-       case OFP_XM_T_ARP_TPA:
-               in = swfcl->swfcl_arp->arp_tip;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(uint32_t));
-
-       if (OFP_OXM_GET_HASMASK(oxm))
-               memcpy(&mask, oxm->oxm_value + sizeof(uint32_t),
-                   sizeof(uint32_t));
-       else
-               mask = UINT32_MAX;
-
-       return !((in & mask) == (mth & mask));
-}
-
-int
-swofp_ox_match_vlan_vid(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint16_t         in, mth, mask = 0;
-
-       if (swfcl->swfcl_vlan == NULL)
-               return (1);
-
-       in = swfcl->swfcl_vlan->vlan_vid;
-       memcpy(&mth, oxm->oxm_value, sizeof(uint16_t));
-
-       if (OFP_OXM_GET_HASMASK(oxm))
-               memcpy(&mask, oxm->oxm_value + sizeof(uint16_t),
-                   sizeof(uint16_t));
-       else
-               mask = UINT16_MAX;
-
-       /*
-        * OpenFlow Switch Specification ver 1.3.5 says if oxm value
-        * is OFP_XM_VID_NONE, matches only packets without a VLAN tag
-        */
-       if (mth == htons(OFP_XM_VID_NONE))
-               return (1);
-
-       /*
-        * OpenFlow Switch Specification ver 1.3.5 says if oxm value and mask
-        * is OFP_XM_VID_PRESENT, matches only packets with a VLAN tag
-        * regardless of its value.
-        */
-       if (ntohs(mth) == OFP_XM_VID_PRESENT &&
-           ntohs(mask) == OFP_XM_VID_PRESENT)
-               return (0);
-
-       in &= htons(EVL_VLID_MASK);
-       mth &= htons(EVL_VLID_MASK);
-
-       return !((in & mask) == (mth & mask));
-}
-
-int
-swofp_ox_match_uint8(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint8_t          in, mth;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_VLAN_PCP:
-               if (swfcl->swfcl_vlan == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_IP_DSCP:
-       case OFP_XM_T_IP_ECN:
-       case OFP_XM_T_IP_PROTO:
-               if ((swfcl->swfcl_ipv4 == NULL &&
-                   swfcl->swfcl_ipv6 == NULL))
-                       return (1);
-               break;
-       case OFP_XM_T_ICMPV4_CODE:
-       case OFP_XM_T_ICMPV4_TYPE:
-               if (swfcl->swfcl_icmpv4 == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_ICMPV6_CODE:
-       case OFP_XM_T_ICMPV6_TYPE:
-               if (swfcl->swfcl_icmpv6 == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_VLAN_PCP:
-               in = swfcl->swfcl_vlan->vlan_pcp;
-               break;
-       case OFP_XM_T_IP_DSCP:
-               if (swfcl->swfcl_ipv4)
-                       in = swfcl->swfcl_ipv4->ipv4_tos >> 2;
-               else
-                       in = swfcl->swfcl_ipv6->ipv6_tclass >> 2;
-               break;
-       case OFP_XM_T_IP_ECN:
-               if (swfcl->swfcl_ipv4)
-                       in = (swfcl->swfcl_ipv4->ipv4_tos) & IPTOS_ECN_MASK;
-               else
-                       in = (swfcl->swfcl_ipv6->ipv6_tclass) & IPTOS_ECN_MASK;
-               break;
-       case OFP_XM_T_IP_PROTO:
-               if (swfcl->swfcl_ipv4)
-                       in = swfcl->swfcl_ipv4->ipv4_proto;
-               else
-                       in = swfcl->swfcl_ipv6->ipv6_nxt;
-               break;
-       case OFP_XM_T_ICMPV4_CODE:
-               in = swfcl->swfcl_icmpv4->icmpv4_code;
-               break;
-       case OFP_XM_T_ICMPV4_TYPE:
-               in = swfcl->swfcl_icmpv4->icmpv4_type;
-               break;
-       case OFP_XM_T_ICMPV6_CODE:
-               in = swfcl->swfcl_icmpv6->icmpv6_code;
-               break;
-       case OFP_XM_T_ICMPV6_TYPE:
-               in = swfcl->swfcl_icmpv6->icmpv6_type;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(uint8_t));
-
-       return !(in == mth);
-
-}
-
-int
-swofp_ox_match_uint16(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint16_t         in, mth;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_TYPE:
-               if (swfcl->swfcl_ether == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_TCP_SRC:
-       case OFP_XM_T_TCP_DST:
-               if (swfcl->swfcl_tcp == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_UDP_SRC:
-       case OFP_XM_T_UDP_DST:
-               if (swfcl->swfcl_udp == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_ARP_OP:
-               if (swfcl->swfcl_arp == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_TYPE:
-               in = swfcl->swfcl_ether->eth_type;
-               break;
-       case OFP_XM_T_TCP_SRC:
-               in = swfcl->swfcl_tcp->tcp_src;
-               break;
-       case OFP_XM_T_TCP_DST:
-               in = swfcl->swfcl_tcp->tcp_dst;
-               break;
-       case OFP_XM_T_UDP_SRC:
-               in = swfcl->swfcl_udp->udp_src;
-               break;
-       case OFP_XM_T_UDP_DST:
-               in = swfcl->swfcl_udp->udp_dst;
-               break;
-       case OFP_XM_T_ARP_OP:
-               in = swfcl->swfcl_arp->_arp_op;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(uint16_t));
-
-       return !(in == mth);
-}
-
-int
-swofp_ox_match_uint32(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint32_t         in, mth, mask, nomask = UINT32_MAX;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_IN_PORT:
-               /* in_port field is always exist in swfcl */
-               break;
-       case OFP_XM_T_IPV6_FLABEL:
-               if (swfcl->swfcl_ipv6 == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_IN_PORT:
-               /*
-                * in_port isn't network byte order because
-                * it's pipeline match field.
-                */
-               in = htonl(swfcl->swfcl_in_port);
-               break;
-       case OFP_XM_T_IPV6_FLABEL:
-               in = swfcl->swfcl_ipv6->ipv6_flow_label;
-               nomask &= IPV6_FLOWLABEL_MASK;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(uint32_t));
-
-       if (OFP_OXM_GET_HASMASK(oxm))
-               memcpy(&mask, oxm->oxm_value + sizeof(uint32_t),
-                   sizeof(uint32_t));
-       else
-               mask = nomask;
-
-       return !((in & mask) == (mth & mask));
-}
-
-int
-swofp_ox_match_uint64(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint64_t         in, mth, mask;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_META:
-               break;
-       case OFP_XM_T_TUNNEL_ID:
-               if (swfcl->swfcl_tunnel == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_META:
-               in = swfcl->swfcl_metadata;
-               break;
-       case OFP_XM_T_TUNNEL_ID:
-               in = swfcl->swfcl_tunnel->tun_key;
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, sizeof(uint64_t));
-
-       if (OFP_OXM_GET_HASMASK(oxm))
-               memcpy(&mask, oxm->oxm_value + sizeof(uint64_t),
-                   sizeof(uint64_t));
-       else
-               mask = UINT64_MAX;
-
-       return !((in & mask) == (mth & mask));
-}
-
-int
-swofp_ox_match_ether_addr(struct switch_flow_classify *swfcl,
-    struct ofp_ox_match *oxm)
-{
-       uint64_t         eth_mask = 0x0000FFFFFFFFFFFFULL;
-       uint64_t         in, mth, mask;
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_SRC:
-       case OFP_XM_T_ETH_DST:
-               if (swfcl->swfcl_ether == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_ARP_SHA:
-       case OFP_XM_T_ARP_THA:
-               if (swfcl->swfcl_arp == NULL)
-                       return (1);
-               break;
-       case OFP_XM_T_IPV6_ND_SLL:
-       case OFP_XM_T_IPV6_ND_TLL:
-               if (swfcl->swfcl_nd6 == NULL)
-                       return (1);
-               break;
-       default:
-               return (1);
-       }
-
-       switch (OFP_OXM_GET_FIELD(oxm)) {
-       case OFP_XM_T_ETH_SRC:
-               in = *(uint64_t *)(swfcl->swfcl_ether->eth_src);
-               break;
-       case OFP_XM_T_ETH_DST:
-               in = *(uint64_t *)(swfcl->swfcl_ether->eth_dst);
-               break;
-       case OFP_XM_T_ARP_SHA:
-               in = *(uint64_t *)(swfcl->swfcl_arp->arp_sha);
-               break;
-       case OFP_XM_T_ARP_THA:
-               in = *(uint64_t *)(swfcl->swfcl_arp->arp_tha);
-               break;
-       case OFP_XM_T_IPV6_ND_SLL:
-       case OFP_XM_T_IPV6_ND_TLL:
-               in = *(uint64_t *)(swfcl->swfcl_nd6->nd6_lladdr);
-               break;
-       }
-
-       memcpy(&mth, oxm->oxm_value, ETHER_ADDR_LEN);
-       if (OFP_OXM_GET_HASMASK(oxm))
-               memcpy(&mask, oxm->oxm_value + ETHER_ADDR_LEN,
-                   ETHER_ADDR_LEN);
-       else
-               mask = UINT64_MAX;
-
-       return !((in & mask & eth_mask) == (mth & mask & eth_mask));
-}
-
-int
-swofp_flow_match_by_swfcl(struct ofp_match *om,
-    struct switch_flow_classify *swfcl)
-{
-       struct ofp_oxm_class    *oxm_handler;
-       struct ofp_ox_match     *oxm;
-
-       OFP_OXM_FOREACH(om, ntohs(om->om_length), oxm) {
-               oxm_handler = swofp_lookup_oxm_handler(oxm);
-               if ((oxm_handler == NULL) ||
-                   (oxm_handler->oxm_match == NULL))
-                       continue;
-
-               if (oxm_handler->oxm_match(swfcl, oxm))
-                       return (1);
-       }
-
-       return (0);
-}
-
-/* TODO: Optimization */
-struct swofp_flow_entry *
-swofp_flow_lookup(struct swofp_flow_table *swft,
-    struct switch_flow_classify *swfcl)
-{
-       struct swofp_flow_entry *swfe, *interim = NULL;
-
-       LIST_FOREACH(swfe, &swft->swft_flow_list, swfe_next) {
-               if (swofp_flow_match_by_swfcl(swfe->swfe_match, swfcl) != 0)
-                       continue;
-
-               if (interim == NULL ||
-                   (interim->swfe_priority < swfe->swfe_priority))
-                       interim = swfe;
-       }
-
-       swft->swft_lookup_count++;
-       if (interim)
-               swft->swft_matched_count++;
-
-       return interim;
-}
-
-/*
- * OpenFlow protocol push/pop VLAN
- */
-
-/* Expand 802.1Q VLAN header from M_VLANTAG mtag if it is exist. */
-struct mbuf *
-swofp_expand_8021q_tag(struct mbuf *m)
-{
-       if ((m->m_flags & M_VLANTAG) == 0)
-               return (m);
-
-       /* H/W tagging supports only 802.1Q */
-       return (vlan_inject(m, ETHERTYPE_VLAN,
-           EVL_VLANOFTAG(m->m_pkthdr.ether_vtag) |
-           EVL_PRIOFTAG(m->m_pkthdr.ether_vtag)));
-}
-
-struct mbuf *
-swofp_action_pop_vlan(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct switch_flow_classify     *swfcl = swpld->swpld_swfcl;
-       struct ether_vlan_header        *evl;
-       struct ether_header              eh;
-
-       /* no vlan tag existing */
-       if (swfcl->swfcl_vlan == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       if ((m->m_flags & M_VLANTAG)) {
-               m->m_flags &= ~M_VLANTAG;
-               return (m);
-       }
-
-       if (m->m_len < sizeof(*evl) &&
-           (m = m_pullup(m, sizeof(*evl))) == NULL)
-               return (NULL);
-       evl = mtod(m, struct ether_vlan_header *);
-
-       if ((ntohs(evl->evl_encap_proto) != ETHERTYPE_VLAN) &&
-           (ntohs(evl->evl_encap_proto) != ETHERTYPE_QINQ)) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       m_copydata(m, 0, ETHER_HDR_LEN, &eh);
-       eh.ether_type = evl->evl_proto;
-
-       m_adj(m, sizeof(*evl));
-       M_PREPEND(m, sizeof(eh), M_DONTWAIT);
-       if (m == NULL)
-               return (NULL);
-       m_copyback(m, 0, sizeof(eh), &eh, M_NOWAIT);
-
-       /*
-        * Update classify for vlan
-        */
-       if (m->m_len < sizeof(*evl) &&
-           (m = m_pullup(m, sizeof(*evl))) == NULL)
-               return (NULL);
-       evl = mtod(m, struct ether_vlan_header *);
-
-       if (ntohs(evl->evl_encap_proto) == ETHERTYPE_VLAN) {
-               swfcl->swfcl_vlan->vlan_tpid = htons(ETHERTYPE_VLAN);
-               swfcl->swfcl_vlan->vlan_vid =
-                   (evl->evl_tag & htons(EVL_VLID_MASK));
-               swfcl->swfcl_vlan->vlan_pcp =
-                   EVL_PRIOFTAG(ntohs(evl->evl_tag));
-       } else {
-               pool_put(&swfcl_pool, swfcl->swfcl_vlan);
-               swfcl->swfcl_vlan = NULL;
-       }
-
-       return (m);
-}
-
-struct mbuf *
-swofp_action_push_vlan(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct switch_flow_classify     *swfcl = swpld->swpld_swfcl;
-       struct ofp_action_push          *oap;
-       struct ether_header             *eh;
-       struct ether_vlan_header         evh;
-
-       /*
-        * Expands 802.1Q VLAN header from M_VLANTAG because switch(4) doesn't
-        * use H/W tagging on port currently.
-        */
-       m = swofp_expand_8021q_tag(m);
-       if (m == NULL)
-               return (NULL);
-
-       oap = (struct ofp_action_push *)oah;
-
-       if ((m->m_len < sizeof(*eh)) &&
-           ((m = m_pullup(m, sizeof(*eh))) == NULL)) {
-               return (NULL);
-       }
-       eh = mtod(m, struct ether_header *);
-
-       switch (ntohs(oap->ap_ethertype)) {
-       case ETHERTYPE_VLAN:
-               if ((ntohs(eh->ether_type) == ETHERTYPE_VLAN) ||
-                   (ntohs(eh->ether_type) == ETHERTYPE_QINQ)) {
-                       m_freem(m);
-                       return (NULL);
-               }
-               break;
-       case ETHERTYPE_QINQ:
-               if (ntohs(eh->ether_type) != ETHERTYPE_VLAN) {
-                       m_freem(m);
-                       return (NULL);
-               }
-               break;
-       default:
-               m_freem(m);
-               return (NULL);
-       }
-
-       if (swfcl->swfcl_vlan == NULL) {
-               swfcl->swfcl_vlan = pool_get(&swfcl_pool, PR_NOWAIT|PR_ZERO);
-               if (swfcl->swfcl_vlan == NULL) {
-                       m_freem(m);
-                       return (NULL);
-               }
-               /* puts default vlan */
-               swfcl->swfcl_vlan->vlan_vid = htons(1);
-       }
-
-       m_copydata(m, 0, ETHER_HDR_LEN, &evh);
-       evh.evl_proto = evh.evl_encap_proto;
-       evh.evl_encap_proto = oap->ap_ethertype;
-       evh.evl_tag = (swfcl->swfcl_vlan->vlan_vid |
-           htons(swfcl->swfcl_vlan->vlan_pcp << EVL_PRIO_BITS));
-
-       m_adj(m, ETHER_HDR_LEN);
-       M_PREPEND(m, sizeof(evh), M_DONTWAIT);
-       if (m == NULL)
-               return (NULL);
-
-       m_copyback(m, 0, sizeof(evh), &evh, M_NOWAIT);
-
-       /*
-        * Update VLAN classification
-        */
-       swfcl->swfcl_vlan->vlan_tpid = oap->ap_ethertype;
-       swfcl->swfcl_vlan->vlan_vid = evh.evl_tag & htons(EVL_VLID_MASK);
-       swfcl->swfcl_vlan->vlan_pcp = EVL_PRIOFTAG(ntohs(evh.evl_tag));
-
-       return (m);
-}
-
-
-/*
- * OpenFlow protocol packet in
- */
-int
-swofp_action_output_controller(struct switch_softc *sc, struct mbuf *m0,
-    struct swofp_pipeline_desc *swpld , uint16_t frame_max_len, uint8_t reason)
-{
-       struct swofp_ofs                *swofs = sc->sc_ofs;
-       struct switch_flow_classify     *swfcl = swpld->swpld_swfcl;
-       struct ofp_packet_in            *pin;
-       struct ofp_match                *om;
-       struct ofp_ox_match             *oxm;
-       struct mbuf                     *m;
-       caddr_t                          tail;
-       int                              match_len;
-
-       if (reason != OFP_PKTIN_REASON_ACTION)
-               frame_max_len = swofs->swofs_switch_config.cfg_miss_send_len;
-       /*
-        * ofp_match in packet_in has only OFP_XM_T_INPORT, OFP_MX_T_META,
-        * OFP_XM_NXMT_TUNNEL_IPV{4|6}_{SRC|DST} and OFP_MX_T_TUNNEL_ID that
-        * if exist, so ofp_match length is determined here.
-        */
-       match_len = (
-           sizeof(*om) +                       /* struct ofp_match */
-           (sizeof(*oxm) + sizeof(uint32_t)) + /* OFP_MX_T_IMPORT */
-           (sizeof(*oxm) + sizeof(uint64_t))   /* OFP_MX_T_META */
-       );
-
-       if (swfcl->swfcl_tunnel) {
-               /* OFP_MX_T_TUNNEL_ID */
-               match_len += (sizeof(*oxm) + sizeof(uint64_t));
-
-               /* OFP_XM_NXMT_TUNNEL_IPV{4|6}_{SRC|DST} */
-               if (swfcl->swfcl_tunnel->tun_af == AF_INET)
-                       match_len += (sizeof(*oxm) + sizeof(uint32_t)) * 2;
-               else if (swfcl->swfcl_tunnel->tun_af == AF_INET6)
-                       match_len += (sizeof(*oxm) +
-                           sizeof(struct in6_addr)) * 2;
-       }
-
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-       if (m == NULL) {
-               m_freem(m0);
-               return (ENOBUFS);
-       }
-       if ((sizeof(*pin) + match_len) >= MHLEN) {
-               MCLGET(m, M_DONTWAIT);
-               if ((m->m_flags & M_EXT) == 0) {
-                       m_freem(m);
-                       m_freem(m0);
-                       return (ENOBUFS);
-               }
-       }
-
-       pin = mtod(m, struct ofp_packet_in *);
-       memset(pin, 0, sizeof(*pin));
-
-       pin->pin_oh.oh_version = OFP_V_1_3;
-       pin->pin_oh.oh_type = OFP_T_PACKET_IN;
-       pin->pin_oh.oh_xid = htonl(swofs->swofs_xidnxt++);
-
-       pin->pin_buffer_id = htonl(OFP_PKTOUT_NO_BUFFER);
-       pin->pin_table_id = swpld->swpld_table_id;
-       pin->pin_cookie = swpld->swpld_cookie;
-       pin->pin_reason = reason;
-
-       if (frame_max_len) {
-               /*
-                * The switch should only truncate packets if it implements
-                * buffering or the controller might end up sending PACKET_OUT
-                * responses with truncated packets that will eventually end
-                * up on the network.
-                */
-               if (frame_max_len < m0->m_pkthdr.len) {
-                       m_freem(m);
-                       m_freem(m0);
-                       return (EMSGSIZE);
-               }
-               pin->pin_total_len = htons(m0->m_pkthdr.len);
-       }
-
-       /*
-        * It's ensured continuous memory space between ofp_mach space
-        */
-       om = &pin->pin_match;
-       swofp_ox_match_put_start(om);
-       swofp_ox_match_put_uint32(om, OFP_XM_T_IN_PORT, swfcl->swfcl_in_port);
-       swofp_ox_match_put_uint64(om, OFP_XM_T_META, swpld->swpld_metadata);
-       if (swfcl->swfcl_tunnel) {
-               swofp_ox_match_put_uint64(om, OFP_XM_T_TUNNEL_ID,
-                   be64toh(swfcl->swfcl_tunnel->tun_key));
-
-               if (swfcl->swfcl_tunnel->tun_af == AF_INET) {
-                       swofp_nx_match_put(om, OFP_XM_NXMT_TUNNEL_IPV4_SRC,
-                           sizeof(uint32_t),
-                           (caddr_t)&swfcl->swfcl_tunnel->tun_ipv4_src);
-                       swofp_nx_match_put(om, OFP_XM_NXMT_TUNNEL_IPV4_DST,
-                           sizeof(uint32_t),
-                           (caddr_t)&swfcl->swfcl_tunnel->tun_ipv4_dst);
-               } else if (swfcl->swfcl_tunnel->tun_af == AF_INET6) {
-                       swofp_nx_match_put(om, OFP_XM_NXMT_TUNNEL_IPV6_SRC,
-                           sizeof(struct in6_addr),
-                           (caddr_t)&swfcl->swfcl_tunnel->tun_ipv6_src);
-                       swofp_nx_match_put(om, OFP_XM_NXMT_TUNNEL_IPV6_DST,
-                           sizeof(struct in6_addr),
-                           (caddr_t)&swfcl->swfcl_tunnel->tun_ipv6_dst);
-               }
-       }
-       match_len = swofp_ox_match_put_end(om); /* match_len include padding */
-
-       /*
-        * Adjust alignment for Ethernet header
-        */
-       tail = (caddr_t)pin +
-           offsetof(struct ofp_packet_in, pin_match) + match_len;
-       memset(tail, 0, ETHER_ALIGN);
-
-       m->m_len = m->m_pkthdr.len =
-           offsetof(struct ofp_packet_in, pin_match) + match_len + ETHER_ALIGN;
-
-       pin->pin_oh.oh_length =
-           htons(m->m_pkthdr.len + ntohs(pin->pin_total_len));
-
-       if (frame_max_len) {
-               /* m_cat() doesn't update the m_pkthdr.len */
-               m_cat(m, m0);
-               m->m_pkthdr.len += ntohs(pin->pin_total_len);
-       }
-
-       (void)swofp_output(sc, m);
-
-       return (0);
-}
-
-struct mbuf *
-swofp_action_output(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct ofp_action_output        *oao;
-       struct switch_port              *swpo;
-       struct mbuf                     *mc;
-       uint32_t                        protected = 0;
-
-       m->m_pkthdr.csum_flags = 0;
-
-       if ((m = swofp_apply_set_field(m, swpld)) == NULL)
-               return (NULL);
-
-       oao = (struct ofp_action_output *)oah;
-
-       switch (ntohl(oao->ao_port)) {
-       case OFP_PORT_CONTROLLER:
-       case OFP_PORT_FLOWTABLE:
-               if ((mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT)) == NULL) {
-                       m_freem(m);
-                       return (NULL);
-               }
-       }
-
-       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,
-                   ntohs(oao->ao_max_len), swpld->swpld_tablemiss ?
-                   OFP_PKTIN_REASON_NO_MATCH : OFP_PKTIN_REASON_ACTION);
-               break;
-       case OFP_PORT_FLOWTABLE:
-               swofp_forward_ofs(sc, swpld->swpld_swfcl, mc);
-               break;
-       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 &&
-                           (protected & swpo->swpo_protected) == 0)
-                               TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
-                                   swpo_fwdp_next);
-               }
-               break;
-       case OFP_PORT_INPUT:
-               TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if (swpo->swpo_port_no ==
-                           swpld->swpld_swfcl->swfcl_in_port) {
-                               TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
-                                   swpo_fwdp_next);
-                               break;
-                       }
-               }
-               break;
-       case OFP_PORT_NORMAL:
-       case OFP_PORT_ALL:
-       case OFP_PORT_ANY:
-               /* no support yet */
-               break;
-       case OFP_PORT_LOCAL:
-               TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       if ((swpo->swpo_flags & IFBIF_LOCAL) &&
-                           (protected & swpo->swpo_protected) == 0) {
-                               TAILQ_INSERT_HEAD(&swpld->swpld_fwdp_q, swpo,
-                                   swpo_fwdp_next);
-                               break;
-                       }
-               }
-               break;
-       default:
-               TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-                       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);
-               }
-               break;
-       }
-
-       if (!TAILQ_EMPTY(&swpld->swpld_fwdp_q)) {
-               if ((mc = m_dup_pkt(m, ETHER_ALIGN, M_NOWAIT)) == NULL) {
-                       m_freem(m);
-                       return (NULL);
-               }
-               switch_port_egress(sc, &swpld->swpld_fwdp_q, mc);
-               TAILQ_INIT(&swpld->swpld_fwdp_q);
-       }
-
-       return (m);
-}
-
-
-struct mbuf *
-swofp_action_group_all(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct swofp_group_entry *swge)
-{
-       struct ofp_bucket               *bucket;
-       struct ofp_action_header        *ah;
-       int                              actions_len;
-       struct swofp_pipeline_desc      *clean_swpld = NULL;
-       struct switch_flow_classify      swfcl;
-       struct mbuf                     *n;
-
-       /* Don't do anything if we don't have buckets. */
-       if (swge->swge_buckets == NULL)
-               return (m);
-
-       OFP_BUCKETS_FOREACH(swge->swge_buckets,
-           swge->swge_buckets_len, bucket) {
-               if (switch_swfcl_dup(swpld->swpld_swfcl, &swfcl) != 0)
-                       goto failed;
-
-               clean_swpld = swofp_pipeline_desc_create(&swfcl);
-               if (clean_swpld == NULL)
-                       goto failed;
-
-               if ((n = m_dup_pkt(m,  ETHER_ALIGN, M_NOWAIT)) == NULL)
-                       goto failed;
-
-               actions_len = (ntohs(bucket->b_len) -
-                   (offsetof(struct ofp_bucket, b_actions)));
-
-               OFP_ACTION_FOREACH(bucket->b_actions, actions_len, ah) {
-                       n = swofp_execute_action(sc, n, clean_swpld, ah);
-                       if (n == NULL)
-                               goto failed;
-               }
-
-               m_freem(n);
-               swofp_pipeline_desc_destroy(clean_swpld);
-               clean_swpld = NULL;
-               switch_swfcl_free(&swfcl);
-       }
-
-       return (m);
-
- failed:
-       m_freem(m);
-       if (clean_swpld)
-               swofp_pipeline_desc_destroy(clean_swpld);
-       return (NULL);
-}
-
-struct mbuf *
-swofp_action_group(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct ofp_action_group         *oag;
-       struct swofp_group_entry        *swge;
-
-       oag = (struct ofp_action_group *)oah;
-
-       swge = swofp_group_entry_lookup(sc, ntohl(oag->ag_group_id));
-       if (swge == NULL) {
-               m_freem(m);
-               return (NULL);
-       }
-
-       swge->swge_packet_count++;
-       swge->swge_byte_count += m->m_pkthdr.len;
-
-       switch (swge->swge_type) {
-       case OFP_GROUP_T_ALL:
-               return swofp_action_group_all(sc, m, swpld, swge);
-       case OFP_GROUP_T_INDIRECT:
-       case OFP_GROUP_T_FAST_FAILOVER:
-       case OFP_GROUP_T_SELECT:
-               m_freem(m);
-               return (NULL);
-       }
-
-       return (m);
-}
-
-struct mbuf *
-swofp_apply_set_field_udp(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct udphdr *uh;
-
-       if (m->m_len < (off + sizeof(*uh)) &&
-           (m = m_pullup(m, off + sizeof(*uh))) == NULL)
-               return NULL;
-
-       uh = (struct udphdr *)((m)->m_data + off);
-
-       if (pre_swfcl->swfcl_udp) {
-               uh->uh_sport = pre_swfcl->swfcl_udp->udp_src;
-               uh->uh_dport = pre_swfcl->swfcl_udp->udp_dst;
-               memcpy(swfcl->swfcl_udp, pre_swfcl->swfcl_udp,
-                   sizeof(*swfcl->swfcl_udp));
-       }
-
-       return (m);
-}
-
-struct mbuf *
-swofp_apply_set_field_tcp(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct tcphdr *th;
-
-       if (m->m_len < (off + sizeof(*th)) &&
-           (m = m_pullup(m, off + sizeof(*th))) == NULL)
-               return NULL;
-
-       th = (struct tcphdr *)((m)->m_data + off);
-
-       if (pre_swfcl->swfcl_tcp) {
-               th->th_sport = pre_swfcl->swfcl_tcp->tcp_src;
-               th->th_dport = pre_swfcl->swfcl_tcp->tcp_dst;
-
-               memcpy(swfcl->swfcl_tcp, pre_swfcl->swfcl_tcp,
-                   sizeof(*swfcl->swfcl_tcp));
-       }
-
-       return (m);
-}
-
-#ifdef INET6
-struct mbuf *
-swofp_apply_set_field_nd6(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct icmp6_hdr                *icmp6;
-       struct nd_neighbor_advert       *nd_na;
-       struct nd_neighbor_solicit      *nd_ns;
-       union nd_opts                    ndopts;
-       int                              icmp6len = m->m_pkthdr.len - off;
-       int                              lladdrlen;
-       uint8_t                         *lladdr;
-
-       if (pre_swfcl->swfcl_nd6 == NULL)
-               return (m);
-
-       IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
-       if (icmp6 == NULL)
-               goto failed;
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_ADVERT:
-               if (icmp6len < sizeof(struct nd_neighbor_advert))
-                       goto failed;
-               break;
-       case ND_NEIGHBOR_SOLICIT:
-               if (icmp6len < sizeof(struct nd_neighbor_solicit))
-                       goto failed;
-               break;
-       }
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_ADVERT:
-               IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m,
-                   off, icmp6len);
-               if (nd_na == NULL)
-                       goto failed;
-
-               nd_na->nd_na_target = pre_swfcl->swfcl_nd6->nd6_target;
-               icmp6len -= sizeof(*nd_na);
-               nd6_option_init(nd_na + 1, icmp6len, &ndopts);
-               if (nd6_options(&ndopts) < 0)
-                       goto failed;
-
-               if (!ndopts.nd_opts_tgt_lladdr)
-                       goto failed;
-
-               lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
-               lladdrlen = (ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3) - 2;
-
-               /* switch(4) only supports Ethernet interfaces */
-               if (lladdrlen != ETHER_ADDR_LEN)
-                       goto failed;
-
-               memcpy(lladdr, pre_swfcl->swfcl_nd6->nd6_lladdr,
-                   ETHER_ADDR_LEN);
-               break;
-       case ND_NEIGHBOR_SOLICIT:
-               IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m,
-                   off, icmp6len);
-               if (nd_ns == NULL)
-                       goto failed;
-
-               nd_ns->nd_ns_target = pre_swfcl->swfcl_nd6->nd6_target;
-               icmp6len -= sizeof(*nd_ns);
-
-               nd6_option_init(nd_ns + 1, icmp6len, &ndopts);
-               if (nd6_options(&ndopts) < 0)
-                       goto failed;
-
-               if (!ndopts.nd_opts_src_lladdr)
-                       goto failed;
-
-               lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
-               lladdrlen = (ndopts.nd_opts_src_lladdr->nd_opt_len << 3) - 2;
-
-               /* switch(4) only supports Ethernet interfaces */
-               if (lladdrlen != ETHER_ADDR_LEN)
-                       goto failed;
-               memcpy(lladdr, pre_swfcl->swfcl_nd6->nd6_lladdr,
-                   ETHER_ADDR_LEN);
-               break;
-       }
-
-       memcpy(swfcl->swfcl_nd6, pre_swfcl->swfcl_nd6,
-           sizeof(*swfcl->swfcl_nd6));
-
-       return (m);
-
- failed:
-       m_freem(m);
-       return (NULL);
-}
-
-struct mbuf *
-swofp_apply_set_field_icmpv6(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct icmp6_hdr        *icmp6;
-
-       IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
-       if (icmp6 == NULL)
-               return (NULL); /* m was already freed */
-
-       if (pre_swfcl->swfcl_icmpv6) {
-               icmp6->icmp6_type = pre_swfcl->swfcl_icmpv6->icmpv6_type;
-               icmp6->icmp6_code = pre_swfcl->swfcl_icmpv6->icmpv6_code;
-
-               memcpy(swfcl->swfcl_icmpv6, pre_swfcl->swfcl_icmpv6,
-                   sizeof(*swfcl->swfcl_icmpv6));
-       }
-
-       m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
-
-       switch (icmp6->icmp6_type) {
-       case ND_NEIGHBOR_ADVERT:
-       case ND_NEIGHBOR_SOLICIT:
-               return swofp_apply_set_field_nd6(m, off, pre_swfcl, swfcl);
-       }
-
-       return (m);
-}
-#endif /* INET6 */
-
-struct mbuf *
-swofp_apply_set_field_icmpv4(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct icmp *icmp;
-
-       if (m->m_len < (off + ICMP_MINLEN) &&
-           (m = m_pullup(m, (off + ICMP_MINLEN))) == NULL)
-               return NULL;
-
-       icmp = (struct icmp *)((m)->m_data + off);
-
-       if (pre_swfcl->swfcl_icmpv4) {
-               icmp->icmp_type = pre_swfcl->swfcl_icmpv4->icmpv4_type;
-               icmp->icmp_code = pre_swfcl->swfcl_icmpv4->icmpv4_code;
-
-               memcpy(swfcl->swfcl_icmpv4, pre_swfcl->swfcl_icmpv4,
-                   sizeof(*swfcl->swfcl_icmpv4));
-       }
-
-       m->m_pkthdr.csum_flags |= M_ICMP_CSUM_OUT;
-
-       return (m);
-}
-
-#ifdef INET6
-struct mbuf *
-swofp_apply_set_field_ipv6(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct ip6_hdr  *ip6;
-       int              hlen;
-       /* max size is 802.1ad header size */
-       u_char           eh_bk[sizeof(struct ether_vlan_header) + EVL_ENCAPLEN];
-
-       if (m->m_len < (off + sizeof(*ip6)) &&
-           (m = m_pullup(m, off + sizeof(*ip6))) == NULL)
-               return (NULL);
-
-       ip6 = (struct ip6_hdr *)(mtod(m, caddr_t) + off);
-
-       if (pre_swfcl->swfcl_ipv6) {
-               /* set version, class and flow label at once */
-               ip6->ip6_flow =  (IPV6_VERSION |
-                   (pre_swfcl->swfcl_ipv6->ipv6_flow_label &
-                   IPV6_FLOWLABEL_MASK) |
-                   htonl(pre_swfcl->swfcl_ipv6->ipv6_tclass << 20));
-               ip6->ip6_hlim = pre_swfcl->swfcl_ipv6->ipv6_hlimit;
-               ip6->ip6_nxt = pre_swfcl->swfcl_ipv6->ipv6_nxt;
-
-               ip6->ip6_src = pre_swfcl->swfcl_ipv6->ipv6_src;
-               ip6->ip6_dst = pre_swfcl->swfcl_ipv6->ipv6_dst;
-
-               memcpy(pre_swfcl->swfcl_ipv6, swfcl->swfcl_ipv6,
-                   sizeof(*pre_swfcl->swfcl_ipv6));
-       }
-
-       hlen = sizeof(*ip6);
-
-       switch (swfcl->swfcl_ipv6->ipv6_nxt) {
-       case IPPROTO_UDP:
-               m = swofp_apply_set_field_udp(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
-               break;
-       case IPPROTO_TCP:
-               m =  swofp_apply_set_field_tcp(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
-               break;
-       case IPPROTO_ICMPV6:
-               m =  swofp_apply_set_field_icmpv6(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               break;
-       }
-
-       /*
-        * Recalculate checksums:
-        * It doesn't use H/W offload because doesn't know to send a frame
-        * from which interface.
-        */
-       m_copydata(m, 0, off, eh_bk);
-       m_adj(m, off);
-
-       if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
-               return (NULL);
-
-       in6_proto_cksum_out(m, NULL);
-
-       M_PREPEND(m, off, M_DONTWAIT);
-       if (m == NULL)
-               return (NULL);
-
-       m_copyback(m, 0, off, eh_bk, M_DONTWAIT);
-
-       return (m);
-}
-#endif /* INET6 */
-
-struct mbuf *
-swofp_apply_set_field_ipv4(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct ip       *ip;
-       int              hlen;
-       /* max size is 802.1ad header size */
-       u_char           eh_bk[sizeof(struct ether_vlan_header) + EVL_ENCAPLEN];
-
-       if (m->m_len < (off + sizeof(*ip)) &&
-           (m = m_pullup(m, off + sizeof(*ip))) == NULL)
-               return (NULL);
-
-       ip = (struct ip *)(mtod(m, caddr_t) + off);
-
-       if (pre_swfcl->swfcl_ipv4) {
-               ip->ip_p = pre_swfcl->swfcl_ipv4->ipv4_proto;
-               ip->ip_tos = pre_swfcl->swfcl_ipv4->ipv4_tos;
-
-               memcpy(&ip->ip_src.s_addr, &pre_swfcl->swfcl_ipv4->ipv4_src,
-                   sizeof(uint32_t));
-               memcpy(&ip->ip_dst.s_addr, &pre_swfcl->swfcl_ipv4->ipv4_dst,
-                   sizeof(uint32_t));
-
-               memcpy(pre_swfcl->swfcl_ipv4, swfcl->swfcl_ipv4,
-                   sizeof(*pre_swfcl->swfcl_ipv4));
-       }
-
-       hlen = (ip->ip_hl << 2);
-
-       switch (swfcl->swfcl_ipv4->ipv4_proto) {
-       case IPPROTO_UDP:
-               m = swofp_apply_set_field_udp(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               m->m_pkthdr.csum_flags |= M_UDP_CSUM_OUT;
-               break;
-       case IPPROTO_TCP:
-               m =  swofp_apply_set_field_tcp(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               m->m_pkthdr.csum_flags |= M_TCP_CSUM_OUT;
-               break;
-       case IPPROTO_ICMP:
-               m =  swofp_apply_set_field_icmpv4(m, (off + hlen),
-                   pre_swfcl, swfcl);
-               if (m == NULL)
-                       return (NULL);
-               break;
-       }
-
-       /*
-        * Recalculate checksums:
-        * It doesn't use H/W offload because doesn't know to send a frame
-        * from which interface.
-        */
-       m_copydata(m, 0, off, eh_bk);
-       m_adj(m, off);
-
-       if (m->m_len < hlen && ((m = m_pullup(m, hlen)) == NULL))
-               return (NULL);
-       ip = mtod(m, struct ip *);
-
-       ip->ip_sum = 0;
-       in_proto_cksum_out(m, NULL);
-       ip->ip_sum = in_cksum(m, hlen);
-
-       M_PREPEND(m, off, M_DONTWAIT);
-       if (m == NULL)
-               return (NULL);
-
-       m_copyback(m, 0, off, eh_bk, M_DONTWAIT);
-
-       return (m);
-}
-
-struct mbuf *
-swofp_apply_set_field_arp( struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct ether_arp *ea;
-
-       if (m->m_len < (off + sizeof(*ea)) &&
-           (m = m_pullup(m, off + sizeof(*ea))) == NULL)
-               return (NULL);
-
-       ea = (struct ether_arp *)((m)->m_data + off);
-
-       if (pre_swfcl->swfcl_arp) {
-               ea->arp_op = pre_swfcl->swfcl_arp->_arp_op;
-
-               memcpy(&ea->arp_sha, pre_swfcl->swfcl_arp->arp_sha,
-                   ETHER_ADDR_LEN);
-               memcpy(&ea->arp_tha, pre_swfcl->swfcl_arp->arp_tha,
-                   ETHER_ADDR_LEN);
-               memcpy(&ea->arp_spa, &pre_swfcl->swfcl_arp->arp_sip,
-                   sizeof(uint32_t));
-               memcpy(&ea->arp_tpa, &pre_swfcl->swfcl_arp->arp_tip,
-                   sizeof(uint32_t));
-               memcpy(swfcl->swfcl_arp, pre_swfcl->swfcl_arp,
-                   sizeof(*swfcl->swfcl_arp));
-       }
-
-       return (m);
-}
-
-struct mbuf *
-swofp_apply_set_field_ether(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct ether_header             *eh;
-       struct ether_vlan_header        *evl = NULL;
-       uint16_t                        *ether_type;
-
-       m = swofp_expand_8021q_tag(m);
-       if (m == NULL)
-               return (NULL);
-
-       /*
-        * pullup to maximum size QinQ header
-        */
-       if ((m = m_pullup(m, (sizeof(*evl) + EVL_ENCAPLEN))) == NULL)
-               return (NULL);
-
-       eh = mtod(m, struct ether_header *);
-
-       switch (ntohs(eh->ether_type)) {
-       case ETHERTYPE_QINQ:
-               off = EVL_ENCAPLEN + sizeof(struct ether_vlan_header);
-               evl = mtod(m, struct ether_vlan_header *);
-               ether_type = (uint16_t *)(mtod(m, caddr_t) + EVL_ENCAPLEN +
-                   offsetof(struct ether_vlan_header, evl_proto));
-               break;
-       case ETHERTYPE_VLAN:
-               off = sizeof(struct ether_vlan_header);
-               evl = mtod(m, struct ether_vlan_header *);
-               ether_type = &evl->evl_proto;
-               break;
-       default:
-               off = sizeof(struct ether_header);
-               ether_type = &eh->ether_type;
-               break;
-       }
-
-       if (pre_swfcl->swfcl_vlan) {
-               switch (ntohs(eh->ether_type)) {
-               case ETHERTYPE_QINQ:
-               case ETHERTYPE_VLAN:
-                       evl->evl_tag = (pre_swfcl->swfcl_vlan->vlan_vid |
-                           htons(pre_swfcl->swfcl_vlan->vlan_pcp <<
-                           EVL_PRIO_BITS));
-                       break;
-               default:
-                       break;
-               }
-
-               /* Update the classifier if it exists. */
-               if (swfcl->swfcl_vlan)
-                       memcpy(swfcl->swfcl_vlan, pre_swfcl->swfcl_vlan,
-                           sizeof(*swfcl->swfcl_vlan));
-       }
-
-       if (pre_swfcl->swfcl_ether) {
-               memcpy(eh->ether_shost, pre_swfcl->swfcl_ether->eth_src,
-                   ETHER_ADDR_LEN);
-               memcpy(eh->ether_dhost, pre_swfcl->swfcl_ether->eth_dst,
-                   ETHER_ADDR_LEN);
-               *ether_type = pre_swfcl->swfcl_ether->eth_type;
-               memcpy(swfcl->swfcl_ether, pre_swfcl->swfcl_ether,
-                   sizeof(*swfcl->swfcl_ether));
-       }
-
-       switch (ntohs(*ether_type)) {
-       case ETHERTYPE_ARP:
-               return swofp_apply_set_field_arp(m, off, pre_swfcl, swfcl);
-       case ETHERTYPE_IP:
-               return swofp_apply_set_field_ipv4(m, off, pre_swfcl, swfcl);
-#ifdef INET6
-       case ETHERTYPE_IPV6:
-               return swofp_apply_set_field_ipv6(m, off, pre_swfcl, swfcl);
-#endif /* INET6 */
-       case ETHERTYPE_MPLS:
-               /* unsupported yet */
-               break;
-       }
-
-       return (m);
-}
-
-struct mbuf *
-swofp_apply_set_field_tunnel(struct mbuf *m, int off,
-    struct switch_flow_classify *pre_swfcl, struct switch_flow_classify *swfcl)
-{
-       struct bridge_tunneltag *brtag;
-
-       if (pre_swfcl->swfcl_tunnel) {
-               if ((brtag = bridge_tunneltag(m)) == NULL) {
-                       m_freem(m);
-                       return (NULL);
-               }
-
-               brtag->brtag_id = be64toh(pre_swfcl->swfcl_tunnel->tun_key);
-
-               if (pre_swfcl->swfcl_tunnel->tun_ipv4_dst.s_addr !=
-                   INADDR_ANY) {
-                       brtag->brtag_peer.sin.sin_family =
-                           brtag->brtag_local.sin.sin_family = AF_INET;
-                       brtag->brtag_local.sin.sin_addr =
-                           pre_swfcl->swfcl_tunnel->tun_ipv4_src;
-                       brtag->brtag_peer.sin.sin_addr =
-                           pre_swfcl->swfcl_tunnel->tun_ipv4_dst;
-               } else if (!IN6_IS_ADDR_UNSPECIFIED(
-                   &pre_swfcl->swfcl_tunnel->tun_ipv6_dst)) {
-                       brtag->brtag_peer.sin6.sin6_family =
-                           brtag->brtag_local.sin.sin_family = AF_INET6;
-                       brtag->brtag_local.sin6.sin6_addr =
-                           pre_swfcl->swfcl_tunnel->tun_ipv6_src;
-                       brtag->brtag_peer.sin6.sin6_addr =
-                           pre_swfcl->swfcl_tunnel->tun_ipv6_dst;
-               } else {
-                       bridge_tunneluntag(m);
-                       m_freem(m);
-                       return (NULL);
-               }
-
-               /*
-                * It can't be used by apply-action instruction.
-                */
-               if (swfcl->swfcl_tunnel) {
-                       memcpy(swfcl->swfcl_tunnel, pre_swfcl->swfcl_tunnel,
-                           sizeof(*pre_swfcl->swfcl_tunnel));
-               }
-       }
-
-       return swofp_apply_set_field_ether(m, 0, pre_swfcl, swfcl);
-}
-
-struct mbuf *
-swofp_apply_set_field(struct mbuf *m, struct swofp_pipeline_desc *swpld)
-{
-       return swofp_apply_set_field_tunnel(m, 0,
-           &swpld->swpld_pre_swfcl, swpld->swpld_swfcl);
-}
-
-struct mbuf *
-swofp_action_set_field(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct ofp_oxm_class *oxm_handler;
-       struct ofp_action_set_field *oasf;
-       struct ofp_ox_match *oxm;
-       struct switch_flow_classify *swfcl, *pre_swfcl;
-
-       oasf = (struct ofp_action_set_field *)oah;
-       oxm = (struct ofp_ox_match *)oasf->asf_field;
-
-       oxm_handler = swofp_lookup_oxm_handler(oxm);
-       if ((oxm_handler == NULL) ||
-           (oxm_handler->oxm_set == NULL))
-               goto failed;
-
-       swfcl = swpld->swpld_swfcl;
-       pre_swfcl = &swpld->swpld_pre_swfcl;
-
-       if (oxm->oxm_class == htons(OFP_OXM_C_NXM_1)) {
-               switch (OFP_OXM_GET_FIELD(oxm)) {
-               case OFP_XM_NXMT_TUNNEL_ID: /* alias OFP_XM_T_TUNNEL_ID */
-               case OFP_XM_NXMT_TUNNEL_IPV4_SRC:
-               case OFP_XM_NXMT_TUNNEL_IPV4_DST:
-               case OFP_XM_NXMT_TUNNEL_IPV6_SRC:
-               case OFP_XM_NXMT_TUNNEL_IPV6_DST:
-                       if (pre_swfcl->swfcl_tunnel)
-                               break;
-                       pre_swfcl->swfcl_tunnel = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_tunnel == NULL)
-                               goto failed;
-                       if (swfcl->swfcl_tunnel)
-                               memcpy(pre_swfcl->swfcl_tunnel,
-                                   swfcl->swfcl_tunnel,
-                                   sizeof(*swfcl->swfcl_tunnel));
-                       break;
-               }
-       } else {
-               switch (OFP_OXM_GET_FIELD(oxm)) {
-               case OFP_XM_T_ETH_SRC:
-               case OFP_XM_T_ETH_DST:
-               case OFP_XM_T_ETH_TYPE:
-                       if (pre_swfcl->swfcl_ether)
-                               break;
-                       pre_swfcl->swfcl_ether = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_ether == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_ether, swfcl->swfcl_ether,
-                           sizeof(*swfcl->swfcl_ether));
-               break;
-               case OFP_XM_T_VLAN_VID:
-               case OFP_XM_T_VLAN_PCP:
-                       if (pre_swfcl->swfcl_vlan)
-                               break;
-                       pre_swfcl->swfcl_vlan = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_vlan == NULL)
-                               goto failed;
-                       if (swfcl->swfcl_vlan)
-                               memcpy(pre_swfcl->swfcl_vlan, swfcl->swfcl_vlan,
-                                   sizeof(*swfcl->swfcl_vlan));
-                       break;
-               case OFP_XM_T_ARP_SHA:
-               case OFP_XM_T_ARP_THA:
-               case OFP_XM_T_ARP_SPA:
-               case OFP_XM_T_ARP_TPA:
-               case OFP_XM_T_ARP_OP:
-                       if (pre_swfcl->swfcl_arp)
-                               break;
-                       pre_swfcl->swfcl_arp = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (swfcl->swfcl_arp == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_arp, swfcl->swfcl_arp,
-                           sizeof(*swfcl->swfcl_arp));
-                       break;
-               case OFP_XM_T_IP_DSCP:
-               case OFP_XM_T_IP_ECN:
-               case OFP_XM_T_IP_PROTO:
-                       if (swfcl->swfcl_ipv4) {
-                               if (pre_swfcl->swfcl_ipv4)
-                                       break;
-                               pre_swfcl->swfcl_ipv4 = pool_get(&swfcl_pool,
-                                   PR_NOWAIT|PR_ZERO);
-                               if (pre_swfcl->swfcl_ipv4 == NULL)
-                                       goto failed;
-                               memcpy(pre_swfcl->swfcl_ipv4, swfcl->swfcl_ipv4,
-                                   sizeof(*swfcl->swfcl_ipv4));
-                       } else if (swfcl->swfcl_ipv6) {
-                               if (pre_swfcl->swfcl_ipv6)
-                                       break;
-                               pre_swfcl->swfcl_ipv6 = pool_get(&swfcl_pool,
-                                   PR_NOWAIT|PR_ZERO);
-                               if (pre_swfcl->swfcl_ipv6 == NULL)
-                                       goto failed;
-                               memcpy(pre_swfcl->swfcl_ipv6, swfcl->swfcl_ipv6,
-                                   sizeof(*swfcl->swfcl_ipv6));
-                       }
-                       break;
-               case OFP_XM_T_IPV4_SRC:
-               case OFP_XM_T_IPV4_DST:
-                       if (pre_swfcl->swfcl_ipv4)
-                               break;
-                       pre_swfcl->swfcl_ipv4 =  pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_ipv4 == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_ipv4, swfcl->swfcl_ipv4,
-                           sizeof(*swfcl->swfcl_ipv4));
-                       break;
-               case OFP_XM_T_IPV6_SRC:
-               case OFP_XM_T_IPV6_DST:
-               case OFP_XM_T_IPV6_FLABEL:
-                       if (pre_swfcl->swfcl_ipv6)
-                               break;
-                       pre_swfcl->swfcl_ipv6 = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_ipv6 == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_ipv6, swfcl->swfcl_ipv6,
-                           sizeof(*swfcl->swfcl_ipv6));
-                       break;
-               case OFP_XM_T_UDP_SRC:
-               case OFP_XM_T_UDP_DST:
-                       if (pre_swfcl->swfcl_udp)
-                               break;
-                       pre_swfcl->swfcl_udp = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_udp == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_udp, swfcl->swfcl_udp,
-                           sizeof(*swfcl->swfcl_udp));
-                       break;
-               case OFP_XM_T_TCP_SRC:
-               case OFP_XM_T_TCP_DST:
-                       if (pre_swfcl->swfcl_tcp)
-                               break;
-                       pre_swfcl->swfcl_tcp = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_tcp == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_tcp, swfcl->swfcl_tcp,
-                           sizeof(*swfcl->swfcl_tcp));
-                       break;
-               case OFP_XM_T_ICMPV4_CODE:
-               case OFP_XM_T_ICMPV4_TYPE:
-                       if (pre_swfcl->swfcl_icmpv4)
-                               break;
-                       pre_swfcl->swfcl_icmpv4 = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_icmpv4 == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_icmpv4, swfcl->swfcl_icmpv4,
-                           sizeof(*swfcl->swfcl_icmpv4));
-                       break;
-               case OFP_XM_T_ICMPV6_CODE:
-               case OFP_XM_T_ICMPV6_TYPE:
-                       if (pre_swfcl->swfcl_icmpv6)
-                               break;
-                       pre_swfcl->swfcl_icmpv6 = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_icmpv6 == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_icmpv6, swfcl->swfcl_icmpv6,
-                           sizeof(*swfcl->swfcl_icmpv6));
-                       break;
-               case OFP_XM_T_IPV6_ND_SLL:
-               case OFP_XM_T_IPV6_ND_TLL:
-               case OFP_XM_T_IPV6_ND_TARGET:
-                       if (pre_swfcl->swfcl_nd6)
-                               break;
-                       pre_swfcl->swfcl_nd6 = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_nd6 == NULL)
-                               goto failed;
-                       memcpy(pre_swfcl->swfcl_nd6, swfcl->swfcl_nd6,
-                           sizeof(*swfcl->swfcl_nd6));
-                       break;
-               case OFP_XM_T_TUNNEL_ID: /* alias OFP_XM_T_TUNNEL_ID */
-                       if (pre_swfcl->swfcl_tunnel)
-                               break;
-                       pre_swfcl->swfcl_tunnel = pool_get(&swfcl_pool,
-                           PR_NOWAIT|PR_ZERO);
-                       if (pre_swfcl->swfcl_tunnel == NULL)
-                               goto failed;
-                       if (swfcl->swfcl_tunnel)
-                               memcpy(pre_swfcl->swfcl_tunnel,
-                                   swfcl->swfcl_tunnel,
-                                   sizeof(*swfcl->swfcl_tunnel));
-                       break;
-               }
-       }
-
-       if (oxm_handler->oxm_set(pre_swfcl, oxm))
-               goto failed;
-
-       return (m);
- failed:
-       m_freem(m);
-       return (NULL);
-}
-
-struct mbuf *
-swofp_execute_action(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct ofp_action_handler       *handler;
-
-       handler = swofp_lookup_action_handler(ntohs(oah->ah_type));
-       if ((handler == NULL) || (handler->action == NULL)) {
-               DPRINTF(sc, "unknown action (type %d)\n",
-                   ntohs(oah->ah_type));
-               m_freem(m);
-               return (NULL);
-       }
-
-       m = handler->action(sc, m, swpld, oah);
-       if (m == NULL)
-               return (NULL);
-
-       return (m);
-}
-
-struct mbuf *
-swofp_execute_action_set_field(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_action_header *oah)
-{
-       struct ofp_action_header        **set_fields;
-       int i;
-
-       set_fields = (struct ofp_action_header **)oah;
-
-       for (i = 0; i < OFP_XM_T_MAX; i++) {
-               if (set_fields[i] == NULL)
-                       continue;
-
-               m = swofp_execute_action(sc, m, swpld, set_fields[i]);
-               if (m == NULL)
-                       return (NULL);
-       }
-
-       return (m);
-}
-
-
-struct mbuf *
-swofp_execute_action_set(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld)
-{
-       struct swofp_action_set *swas;
-       int                      i;
-
-       TAILQ_INIT(&swpld->swpld_fwdp_q);
-       swas = swpld->swpld_action_set;
-       swpld->swpld_swfcl->swfcl_cookie = UINT64_MAX;
-
-       for (i = 0 ; i < nitems(ofp_action_handlers); i++) {
-               if (swas[i].swas_action == NULL)
-                       continue;
-
-               if (swas[i].swas_type == OFP_ACTION_SET_FIELD)
-                       m = swofp_execute_action_set_field(sc, m, swpld,
-                           swas[i].swas_action);
-               else
-                       m = swofp_execute_action(sc, m, swpld,
-                           swas[i].swas_action);
-
-               if (m == NULL)
-                       break;
-       }
-
-       m_freem(m);
-
-       return (NULL);
-}
-
-struct mbuf *
-swofp_apply_actions(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_pipeline_desc *swpld, struct ofp_instruction_actions *oia)
-{
-       struct ofp_action_header        *oah;
-
-       TAILQ_INIT(&swpld->swpld_fwdp_q);
-
-       OFP_I_ACTIONS_FOREACH(oia, oah) {
-               m = swofp_execute_action(sc, m, swpld, oah);
-               if (m == NULL)
-                       return (NULL);
-       }
-
-       return (m);
-}
-
-struct swofp_action_set *
-swofp_lookup_action_set(struct swofp_pipeline_desc *swpld, uint16_t type)
-{
-       int     i;
-
-       for (i = 0; i < nitems(ofp_action_handlers); i ++) {
-               if (swpld->swpld_action_set[i].swas_type == type)
-                       return (&swpld->swpld_action_set[i]);
-       }
-
-       return (NULL);
-}
-
-void
-swofp_write_actions_set_field(struct swofp_action_set *swas,
-    struct ofp_action_header *oah)
-{
-       struct ofp_action_header        **set_fields;
-       struct ofp_action_set_field     *oasf;
-       struct ofp_ox_match             *oxm;
-
-       set_fields = (struct ofp_action_header **)swas->swas_action;
-
-       oasf = (struct ofp_action_set_field *)oah;
-       oxm = (struct ofp_ox_match *)oasf->asf_field;
-
-       set_fields[OFP_OXM_GET_FIELD(oxm)] = oah;
-}
-
-int
-swofp_write_actions(struct ofp_instruction_actions *oia,
-    struct swofp_pipeline_desc *swpld)
-{
-       struct swofp_action_set         *swas;
-       struct ofp_action_header        *oah;
-
-       OFP_I_ACTIONS_FOREACH(oia, oah) {
-               swas = swofp_lookup_action_set(swpld, ntohs(oah->ah_type));
-               if (swas == NULL)
-                       return (ENOENT);
-
-               if (ntohs(oah->ah_type) == OFP_ACTION_SET_FIELD)
-                       swofp_write_actions_set_field(swas, oah);
-               else
-                       swas->swas_action = oah;
-       }
-
-       return (0);
-}
-
-void
-swofp_clear_actions_set_field(struct swofp_action_set *swas,
-    struct ofp_action_header *oah)
-{
-       struct ofp_action_header        **set_fields;
-       struct ofp_action_set_field     *oasf;
-       struct ofp_ox_match             *oxm;
-
-       set_fields = (struct ofp_action_header **)swas->swas_action;
-
-       oasf = (struct ofp_action_set_field *)oah;
-       oxm = (struct ofp_ox_match *)oasf->asf_field;
-
-       set_fields[OFP_OXM_GET_FIELD(oxm)] = NULL;
-}
-
-int
-swofp_clear_actions(struct ofp_instruction_actions *oia,
-    struct swofp_pipeline_desc *swpld)
-{
-       struct swofp_action_set         *swas;
-       struct ofp_action_header        *oah;
-
-       OFP_I_ACTIONS_FOREACH(oia, oah) {
-               swas = swofp_lookup_action_set(swpld, ntohs(oah->ah_type));
-               if (swas == NULL)
-                       return (ENOENT);
-
-               if (ntohs(oah->ah_type) == OFP_ACTION_SET_FIELD)
-                       swofp_clear_actions_set_field(swas, oah);
-               else
-                       swas->swas_action = NULL;
-       }
-
-       return (0);
-}
-
-void
-swofp_write_metadata(struct ofp_instruction_write_metadata *iowm,
-    struct swofp_pipeline_desc *swpld)
-{
-       uint64_t val, mask;
-
-       val = iowm->iwm_metadata;
-       mask = iowm->iwm_metadata_mask;
-
-       swpld->swpld_metadata = (val & mask);
-}
-
-void
-swofp_forward_ofs(struct switch_softc *sc, struct switch_flow_classify *swfcl,
-    struct mbuf *m)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct swofp_flow_entry         *swfe;
-       struct swofp_flow_table         *swft;
-       struct swofp_pipeline_desc      *swpld;
-       int                              error;
-       uint8_t                          next_table_id = 0;
-
-       swpld = swofp_pipeline_desc_create(swfcl);
-       if (swpld == NULL) {
-               m_freem(m);
-               return;
-       }
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if (swft->swft_table_id != next_table_id)
-                       continue;
-
-               /* XXX
-                * The metadata is pipeline parameters but it uses same match
-                * framework for matching so it is copy to flow classify.
-                */
-               swpld->swpld_swfcl->swfcl_metadata = swpld->swpld_metadata;
-
-               if ((swfe = swofp_flow_lookup(swft,
-                   swpld->swpld_swfcl)) == NULL)
-                       break;
-
-               /* Set pipeline parameters */
-               swpld->swpld_cookie = swfe->swfe_cookie;
-               swpld->swpld_table_id = swft->swft_table_id;
-               swpld->swpld_tablemiss = swfe->swfe_tablemiss;
-
-               /* Update statistics */
-               nanouptime(&swfe->swfe_idle_time);
-               swfe->swfe_packet_cnt++;
-               swfe->swfe_byte_cnt += m->m_pkthdr.len;
-
-               if (swfe->swfe_meter) {
-                       /* TODO: Here is meter instruction */
-               }
-
-               if (swfe->swfe_apply_actions) {
-                       m = swofp_apply_actions(sc, m, swpld,
-                           swfe->swfe_apply_actions);
-                       if (m == NULL)
-                               goto out;
-               }
-
-               if (swfe->swfe_clear_actions) {
-                       error = swofp_clear_actions(
-                           swfe->swfe_clear_actions, swpld);
-                       if (error)
-                               goto out;
-               }
-
-               if (swfe->swfe_write_actions) {
-                       error = swofp_write_actions(
-                           swfe->swfe_write_actions, swpld);
-                       if (error)
-                               goto out;
-               }
-
-               if (swfe->swfe_write_metadata)
-                       swofp_write_metadata(swfe->swfe_write_metadata, swpld);
-
-               if (swfe->swfe_goto_table)
-                       next_table_id = swfe->swfe_goto_table->igt_table_id;
-               else
-                       break;
-       }
-
-       m = swofp_execute_action_set(sc, m, swpld);
- out:
-       m_freem(m);
-       swofp_pipeline_desc_destroy(swpld);
-}
-
-int
-swofp_input(struct switch_softc *sc, struct mbuf *m)
-{
-#if NBPFILTER > 0
-       struct swofp_ofs        *swofs = sc->sc_ofs;
-#endif
-       struct ofp_header       *oh;
-       ofp_msg_handler          handler;
-       uint16_t                 ohlen;
-
-       if (m->m_len < sizeof(*oh) &&
-           (m = m_pullup(m, sizeof(*oh))) == NULL)
-               return (ENOBUFS);
-
-       oh = mtod(m, struct ofp_header *);
-
-       ohlen = ntohs(oh->oh_length);
-       /* Validate that we have a sane header. */
-       KASSERT(m->m_flags & M_PKTHDR);
-       if (ohlen < sizeof(*oh) || m->m_pkthdr.len < ohlen) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (0);
-       }
-
-       if (m->m_len < ohlen && (m = m_pullup(m, ohlen)) == NULL)
-               return (ENOBUFS);
-
-#if NBPFILTER > 0
-       if (sc->sc_ofbpf)
-               switch_mtap(sc->sc_ofbpf, m, BPF_DIRECTION_IN,
-                   swofs->swofs_datapath_id);
-#endif
-
-       handler = swofp_lookup_msg_handler(oh->oh_type);
-       if (handler)
-               (*handler)(sc, m);
-       else
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_TYPE);
-
-       return (0);
-}
-
-int
-swofp_output(struct switch_softc *sc, struct mbuf *m)
-{
-#if NBPFILTER > 0
-       struct swofp_ofs        *swofs = sc->sc_ofs;
-#endif
-
-       if (sc->sc_swdev == NULL) {
-               m_freem(m);
-               return (ENXIO);
-       }
-
-#if NBPFILTER > 0
-       if (sc->sc_ofbpf)
-               switch_mtap(sc->sc_ofbpf, m, BPF_DIRECTION_OUT,
-                   swofs->swofs_datapath_id);
-#endif
-
-       if (sc->sc_swdev->swdev_output(sc, m) != 0)
-               return (ENOBUFS);
-
-       return (0);
-}
-
-/*
- * OpenFlow protocol HELLO message handler
- */
-int
-swofp_recv_hello(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_header       *oh;
-
-       oh = mtod(m, struct ofp_header *);
-
-       if (oh->oh_version != OFP_V_1_3)
-               swofp_send_error(sc, m,
-                   OFP_ERRTYPE_HELLO_FAILED, OFP_ERRHELLO_INCOMPATIBLE);
-       else
-               m_freem(m);
-
-       return (0);
-}
-
-void
-swofp_send_hello(struct switch_softc *sc)
-{
-       struct swofp_ofs                *swofs = sc->sc_ofs;
-       struct mbuf                     *m;
-       struct ofp_header               *oh;
-
-       MGETHDR(m, M_DONTWAIT, MT_DATA);
-       if (m == NULL)
-               return;         /* XXX */
-
-       oh = mtod(m, struct ofp_header *);
-
-       oh->oh_version = OFP_V_1_3;
-       oh->oh_type = OFP_T_HELLO;
-       oh->oh_length = htons(sizeof(*oh));
-       oh->oh_xid = htonl(swofs->swofs_xidnxt++);
-       m->m_len = m->m_pkthdr.len = sizeof(*oh);
-
-       (void)swofp_output(sc, m);
-}
-
-/*
- * OpenFlow protocol Error message
- */
-void
-swofp_send_error(struct switch_softc *sc, struct mbuf *m,
-    uint16_t type, uint16_t code)
-{
-       struct mbuf             *n;
-       struct ofp_header       *oh;
-       struct ofp_error        *oe;
-       int                      off;
-       uint32_t                 xid;
-       uint16_t                 len;
-
-       /* Reuse mbuf from request message */
-       oh = mtod(m, struct ofp_header *);
-
-       /* Save data for the response and copy back later. */
-       len = min(ntohs(oh->oh_length), OFP_ERRDATA_MAX);
-       if (len < m->m_pkthdr.len)
-               m_adj(m, len - m->m_pkthdr.len);
-       xid = oh->oh_xid;
-
-       if ((n = m_makespace(m, 0, sizeof(struct ofp_error), &off)) == NULL) {
-               m_freem(m);
-               return;
-       }
-       /* if skip is 0, off is also 0 */
-       KASSERT(off == 0);
-
-       oe = mtod(n, struct ofp_error *);
-
-       oe->err_oh.oh_version = OFP_V_1_3;
-       oe->err_oh.oh_type = OFP_T_ERROR;
-       oe->err_oh.oh_length = htons(sizeof(struct ofp_error) + len);
-       oe->err_oh.oh_xid = xid;
-       oe->err_type = htons(type);
-       oe->err_code = htons(code);
-
-       (void)swofp_output(sc, m);
-}
-
-
-/*
- * OpenFlow protocol Echo message
- */
-int
-swofp_recv_echo(struct switch_softc *sc, struct mbuf *m)
-{
-       return swofp_send_echo(sc, m);
-}
-
-int
-swofp_send_echo(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_header       *oh;
-
-       oh = mtod(m, struct ofp_header *);
-       oh->oh_type = OFP_T_ECHO_REPLY;
-
-       return (swofp_output(sc, m));
-}
-
-
-/*
- * Feature request handler
- */
-int
-swofp_recv_features_req(struct switch_softc *sc, struct mbuf *m)
-{
-
-       struct swofp_ofs                *swofs = sc->sc_ofs;
-       struct ofp_header               *oh;
-       struct ofp_switch_features       swf;
-
-       oh = mtod(m, struct ofp_header *);
-
-       memset(&swf, 0, sizeof(swf));
-       memcpy(&swf, oh, sizeof(*oh));
-       swf.swf_oh.oh_type = OFP_T_FEATURES_REPLY;
-       swf.swf_oh.oh_length = htons(sizeof(swf));
-
-       swf.swf_datapath_id = htobe64(swofs->swofs_datapath_id);
-       swf.swf_nbuffers = htonl(0); /* no buffer now */
-       swf.swf_ntables = OFP_TABLE_ID_MAX;
-       swf.swf_aux_id = 0;
-       swf.swf_capabilities = htonl(OFP_SWCAP_FLOW_STATS |
-           OFP_SWCAP_TABLE_STATS | OFP_SWCAP_PORT_STATS |
-           OFP_SWCAP_GROUP_STATS);
-
-       m_copyback(m, 0, sizeof(swf), (caddr_t)&swf, M_WAIT);
-
-       return (swofp_output(sc, m));
-}
-
-/*
- * Get config handler
- */
-int
-swofp_recv_config_req(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *swofs = sc->sc_ofs;
-       struct ofp_switch_config         osc;
-
-       memcpy(&osc.cfg_oh, mtod(m, caddr_t), sizeof(struct ofp_header));
-       osc.cfg_oh.oh_type = OFP_T_GET_CONFIG_REPLY;
-       osc.cfg_oh.oh_length = htons(sizeof(osc));
-
-       osc.cfg_flags = htons(swofs->swofs_switch_config.cfg_flags);
-       osc.cfg_miss_send_len =
-           htons(swofs->swofs_switch_config.cfg_miss_send_len);
-       if (m_copyback(m, 0, sizeof(osc), &osc, M_NOWAIT)) {
-               m_freem(m);
-               return (-1);
-       }
-
-       return (swofp_output(sc, m));
-}
-
-/*
- * Set config handler
- */
-int
-swofp_recv_set_config(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *swofs = sc->sc_ofs;
-       struct ofp_switch_config        *swc;
-
-       swc = mtod(m, struct ofp_switch_config *);
-       if (ntohs(swc->cfg_oh.oh_length) < sizeof(*swc)) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (-1);
-       }
-
-       /*
-        * Support only "normal" fragment handle
-        */
-       swofs->swofs_switch_config.cfg_flags = OFP_CONFIG_FRAG_NORMAL;
-       swofs->swofs_switch_config.cfg_miss_send_len =
-           ntohs(swc->cfg_miss_send_len);
-
-       m_freem(m);
-
-       return (0);
-}
-
-/*
- * OpenFlow protocol FLOW REMOVE message handlers
- */
-int
-swofp_send_flow_removed(struct switch_softc *sc, struct swofp_flow_entry *swfe,
-    uint8_t reason)
-{
-       struct ofp_flow_removed *ofr;
-       struct timespec          now, duration;
-       struct mbuf             *m;
-       int                      match_len;
-
-       match_len = ntohs(swfe->swfe_match->om_length);
-
-       MGETHDR(m, M_WAITOK, MT_DATA);
-       if (m == NULL)
-               return (ENOBUFS);
-       if ((sizeof(*ofr) + match_len) >= MHLEN) {
-               MCLGET(m, M_WAITOK);
-               if ((m->m_flags & M_EXT) == 0) {
-                       m_freem(m);
-                       return (ENOBUFS);
-               }
-       }
-
-       ofr = mtod(m, struct ofp_flow_removed *);
-
-       ofr->fr_oh.oh_version = OFP_V_1_3;
-       ofr->fr_oh.oh_type = OFP_T_FLOW_REMOVED;
-       ofr->fr_oh.oh_xid = htonl(sc->sc_ofs->swofs_xidnxt++);
-
-       ofr->fr_cookie = htobe64(swfe->swfe_cookie);
-       ofr->fr_priority = htons(swfe->swfe_priority);
-       ofr->fr_reason = reason;
-       ofr->fr_table_id = swfe->swfe_table_id;
-
-       nanouptime(&now);
-       timespecsub(&now, &swfe->swfe_installed_time, &duration);
-       ofr->fr_duration_sec = ntohl((int)duration.tv_sec);
-       ofr->fr_priority = htons(swfe->swfe_priority);
-       ofr->fr_idle_timeout = htons(swfe->swfe_idle_timeout);
-       ofr->fr_hard_timeout = htons(swfe->swfe_hard_timeout);
-       ofr->fr_byte_count = htobe64(swfe->swfe_byte_cnt);
-       ofr->fr_packet_count = htobe64(swfe->swfe_packet_cnt);
-
-       memcpy(&ofr->fr_match, swfe->swfe_match, match_len);
-
-       /* match_len inclusive ofp_match header length*/
-       ofr->fr_oh.oh_length =
-           htons(sizeof(*ofr) + match_len - sizeof(struct ofp_match));
-
-       m->m_len = m->m_pkthdr.len =
-           sizeof(*ofr) + match_len - sizeof(struct ofp_match);
-
-       return (swofp_output(sc, m));
-}
-
-/*
- * OpenFlow protocol FLOW MOD message handlers
- */
-int
-swofp_flow_entry_put_instructions(struct switch_softc *sc, struct mbuf *m,
-    struct swofp_flow_entry *swfe, uint16_t *etype, uint16_t *error)
-{
-       struct ofp_flow_mod     *ofm;
-       struct ofp_instruction  *oi;
-       caddr_t                  inst;
-       int                      start, len, off;
-
-       *etype = OFP_ERRTYPE_BAD_INSTRUCTION;
-
-       ofm = mtod(m, struct ofp_flow_mod *);
-
-       /*
-        * Clear instructions from flow entry. It's necessary to only modify
-        * flow but it's no problem to clear on adding flow because the flow
-        * entry doesn't have any instructions. So it's always called.
-        */
-       swofp_flow_entry_instruction_free(swfe);
-
-       start = OFP_FLOW_MOD_MSG_INSTRUCTION_OFFSET(ofm);
-       len = ntohs(ofm->fm_oh.oh_length) - start;
-       for (off = start; off < start + len; off += ntohs(oi->i_len)) {
-               oi = (struct ofp_instruction *)(mtod(m, caddr_t) + off);
-
-               if (swofp_validate_flow_instruction(sc, oi,
-                   len - (off - start), etype, error))
-                       return (-1);
-
-               if ((inst = malloc(ntohs(oi->i_len), M_DEVBUF,
-                   M_DONTWAIT|M_ZERO)) == NULL) {
-                       *error = OFP_ERRFLOWMOD_UNKNOWN;
-                       return (-1);
-               }
-               memcpy(inst, oi, ntohs(oi->i_len));
-
-               switch (ntohs(oi->i_type)) {
-               case OFP_INSTRUCTION_T_GOTO_TABLE:
-                       if (swfe->swfe_goto_table)
-                               free(swfe->swfe_goto_table, M_DEVBUF,
-                                   ntohs(swfe->swfe_goto_table->igt_len));
-
-                       swfe->swfe_goto_table =
-                           (struct ofp_instruction_goto_table *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_WRITE_META:
-                       if (swfe->swfe_write_metadata)
-                               free(swfe->swfe_write_metadata, M_DEVBUF,
-                                   ntohs(swfe->swfe_write_metadata->iwm_len));
-
-                       swfe->swfe_write_metadata =
-                           (struct ofp_instruction_write_metadata *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_WRITE_ACTIONS:
-                       if (swfe->swfe_write_actions)
-                               free(swfe->swfe_write_actions, M_DEVBUF,
-                                   ntohs(swfe->swfe_write_actions->ia_len));
-
-                       swfe->swfe_write_actions =
-                           (struct ofp_instruction_actions *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_APPLY_ACTIONS:
-                       if (swfe->swfe_apply_actions)
-                               free(swfe->swfe_apply_actions, M_DEVBUF,
-                                   ntohs(swfe->swfe_apply_actions->ia_len));
-
-                       swfe->swfe_apply_actions =
-                           (struct ofp_instruction_actions *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_CLEAR_ACTIONS:
-                       if (swfe->swfe_clear_actions)
-                               free(swfe->swfe_clear_actions, M_DEVBUF,
-                                   ntohs(swfe->swfe_clear_actions->ia_len));
-
-                       swfe->swfe_clear_actions =
-                           (struct ofp_instruction_actions *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_METER:
-                       if (swfe->swfe_meter)
-                               free(swfe->swfe_meter, M_DEVBUF,
-                                   ntohs(swfe->swfe_meter->im_len));
-
-                       swfe->swfe_meter = (struct ofp_instruction_meter *)inst;
-                       break;
-               case OFP_INSTRUCTION_T_EXPERIMENTER:
-                       if (swfe->swfe_experimenter)
-                               free(swfe->swfe_experimenter, M_DEVBUF,
-                                   ntohs(swfe->swfe_experimenter->ie_len));
-
-                       swfe->swfe_experimenter =
-                           (struct ofp_instruction_experimenter *)inst;
-                       break;
-               default:
-                       free(inst, M_DEVBUF, ntohs(oi->i_len));
-                       break;
-               }
-       }
-
-       return (0);
-}
-
-int
-swofp_flow_mod_cmd_add(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct ofp_flow_mod             *ofm;
-       struct ofp_match                *om;
-       struct swofp_flow_entry         *swfe, *old_swfe;
-       struct swofp_flow_table         *swft;
-       int                              omlen;
-       uint16_t                         error, etype;
-
-       etype = OFP_ERRTYPE_FLOW_MOD_FAILED;
-       ofm = mtod(m, struct ofp_flow_mod *);
-       om = &ofm->fm_match;
-
-       if (OFP_TABLE_ID_MAX < ofm->fm_table_id) {
-               error = OFP_ERRFLOWMOD_TABLE_ID;
-               goto ofp_error;
-       }
-
-       if (ofm->fm_cookie == UINT64_MAX) {
-                /* XXX What is best error code? */
-               error = OFP_ERRFLOWMOD_UNKNOWN;
-               goto ofp_error;
-       }
-
-       omlen = ntohs(om->om_length);
-       /*
-        * 1) ofp_match header must have at least its own size,
-        *    otherwise memcpy() will fail later;
-        * 2) OXM filters can't be bigger than the packet.
-        */
-       if (omlen < sizeof(*om) ||
-           omlen >= (m->m_len - sizeof(*ofm))) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               error = OFP_ERRMATCH_BAD_LEN;
-               goto ofp_error;
-       }
-
-       if ((swft = swofp_flow_table_add(sc, ofm->fm_table_id)) == NULL) {
-               error = OFP_ERRFLOWMOD_TABLE_ID;
-               goto ofp_error;
-       }
-
-       if (swft->swft_flow_num >= ofs->swofs_flow_max_entry) {
-               error = OFP_ERRFLOWMOD_TABLE_FULL;
-               goto ofp_error;
-       }
-
-       /* Validate that the OXM are in-place and correct. */
-       if (swofp_validate_flow_match(om, &error)) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               goto ofp_error;
-       }
-
-       if ((old_swfe = swofp_flow_search_by_table(swft, om,
-           ntohs(ofm->fm_priority)))) {
-               if (ntohs(ofm->fm_flags) & OFP_FLOWFLAG_CHECK_OVERLAP) {
-                       error = OFP_ERRFLOWMOD_OVERLAP;
-                       goto ofp_error;
-               }
-       }
-
-       if ((swfe = malloc(sizeof(*swfe), M_DEVBUF,
-           M_DONTWAIT|M_ZERO)) == NULL) {
-               error = OFP_ERRFLOWMOD_UNKNOWN;
-               goto ofp_error;
-       }
-
-       swfe->swfe_priority = ntohs(ofm->fm_priority);
-       swfe->swfe_cookie =  be64toh(ofm->fm_cookie);
-       swfe->swfe_flags = ntohs(ofm->fm_flags);
-       swfe->swfe_idle_timeout = ntohs(ofm->fm_idle_timeout);
-       swfe->swfe_hard_timeout = ntohs(ofm->fm_hard_timeout);
-       nanouptime(&swfe->swfe_installed_time);
-       nanouptime(&swfe->swfe_idle_time);
-
-       if ((swfe->swfe_match = malloc(omlen, M_DEVBUF,
-           M_DONTWAIT|M_ZERO)) == NULL) {
-               error = OFP_ERRFLOWMOD_UNKNOWN;
-               goto ofp_error_free_flow;
-       }
-       memcpy(swfe->swfe_match, om, omlen);
-
-       /*
-        * If the ofp_match structure is empty and priority is zero, then
-        * this is a special flow type called table-miss which is the last
-        * flow to match.
-        */
-       if (omlen == sizeof(*om) && swfe->swfe_priority == 0)
-               swfe->swfe_tablemiss = 1;
-
-       if (swofp_flow_entry_put_instructions(sc, m, swfe, &etype, &error))
-               goto ofp_error_free_flow;
-
-       if (old_swfe) {
-               if (!(ntohs(ofm->fm_flags) & OFP_FLOWFLAG_RESET_COUNTS)) {
-                       swfe->swfe_packet_cnt = old_swfe->swfe_packet_cnt;
-                       swfe->swfe_byte_cnt = old_swfe->swfe_byte_cnt;
-               }
-               /*
-                * Doesn't need to send flow remove message because
-                * this deleted flow cause by internal reason
-                */
-               swfe->swfe_flags &= ~(OFP_FLOWFLAG_SEND_FLOW_REMOVED);
-               swofp_flow_entry_delete(sc, swft, old_swfe,
-                   OFP_FLOWREM_REASON_DELETE);
-       }
-
-       swofp_flow_entry_add(sc, swft, swfe);
-
-       m_freem(m);
-       return (0);
-
- ofp_error_free_flow:
-       swofp_flow_entry_free(&swfe);
- ofp_error:
-       swofp_send_error(sc, m, etype, error);
-       return (0);
-}
-
-int
-swofp_flow_mod_cmd_common_modify(struct switch_softc *sc, struct mbuf *m,
-    int strict)
-{
-       struct ofp_flow_mod             *ofm;
-       struct ofp_match                *om;
-       struct swofp_flow_entry         *swfe;
-       struct swofp_flow_table         *swft;
-       int                              omlen;
-       uint16_t                         error, etype;
-
-       etype = OFP_ERRTYPE_FLOW_MOD_FAILED;
-
-       ofm = mtod(m, struct ofp_flow_mod *);
-       om = &ofm->fm_match;
-
-       if (OFP_TABLE_ID_MAX < ofm->fm_table_id) {
-               error = OFP_ERRFLOWMOD_TABLE_ID;
-               goto ofp_error;
-       }
-
-       if (ofm->fm_cookie == UINT64_MAX) {
-               /* XXX What is best error code? */
-               error = OFP_ERRFLOWMOD_UNKNOWN;
-               goto ofp_error;
-       }
-
-       omlen = ntohs(om->om_length);
-       /*
-        * 1) ofp_match header must have at least its own size,
-        *    otherwise memcpy() will fail later;
-        * 2) OXM filters can't be bigger than the packet.
-        */
-       if (omlen < sizeof(*om) ||
-           omlen >= (m->m_len - sizeof(*ofm))) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               error = OFP_ERRMATCH_BAD_LEN;
-               goto ofp_error;
-       }
-
-       /* Validate that the OXM are in-place and correct. */
-       if (swofp_validate_flow_match(om, &error)) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               goto ofp_error;
-       }
-
-       if ((swft = swofp_flow_table_lookup(sc, ofm->fm_table_id)) == NULL) {
-               error = OFP_ERRFLOWMOD_TABLE_ID;
-               goto ofp_error;
-       }
-
-       LIST_FOREACH(swfe, &swft->swft_flow_list, swfe_next) {
-               if (strict && !swofp_flow_cmp_strict(swfe, om,
-                   ntohs(ofm->fm_priority)))
-                       continue;
-               else if (!swofp_flow_cmp_non_strict(swfe, om))
-                       continue;
-
-               if (!swofp_flow_filter(swfe, be64toh(ofm->fm_cookie),
-                   be64toh(ofm->fm_cookie_mask), ntohl(ofm->fm_out_port),
-                   ntohl(ofm->fm_out_group)))
-                       continue;
-
-               if (swofp_flow_entry_put_instructions(sc, m, swfe, &etype,
-                   &error)) {
-                       /*
-                        * If error occurs in swofp_flow_entry_put_instructions,
-                        * the flow entry might be half-way modified. So the
-                        * flow entry is delete here.
-                        */
-                       swofp_flow_entry_delete(sc, swft, swfe,
-                           OFP_FLOWREM_REASON_DELETE);
-                       etype = OFP_ERRTYPE_BAD_INSTRUCTION;
-                       goto ofp_error;
-               }
-
-               if (ntohs(ofm->fm_flags) & OFP_FLOWFLAG_RESET_COUNTS) {
-                       swfe->swfe_packet_cnt = 0;
-                       swfe->swfe_byte_cnt = 0;
-               }
-       }
-
-       m_freem(m);
-       return (0);
-
- ofp_error:
-       swofp_send_error(sc, m, etype, error);
-       return (0);
-}
-
-int
-swofp_flow_mod_cmd_modify(struct switch_softc *sc, struct mbuf *m)
-{
-       return swofp_flow_mod_cmd_common_modify(sc, m, 0);
-}
-
-int
-swofp_flow_mod_cmd_modify_strict(struct switch_softc *sc, struct mbuf *m)
-{
-       return swofp_flow_mod_cmd_common_modify(sc, m, 1);
-}
-
-
-int
-swofp_flow_mod_cmd_common_delete(struct switch_softc *sc, struct mbuf *m,
-    int strict)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct ofp_flow_mod     *ofm;
-       struct ofp_match        *om;
-       struct swofp_flow_table *swft;
-       int                      omlen;
-       uint16_t                 error, etype = OFP_ERRTYPE_FLOW_MOD_FAILED;
-
-       ofm = (struct ofp_flow_mod *)(mtod(m, caddr_t));
-       om = &ofm->fm_match;
-
-       omlen = ntohs(om->om_length);
-       /*
-        * 1) ofp_match header must have at least its own size,
-        *    otherwise memcpy() will fail later;
-        * 2) OXM filters can't be bigger than the packet.
-        */
-       if (omlen < sizeof(*om) ||
-           omlen >= (m->m_len - sizeof(*ofm))) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               error = OFP_ERRMATCH_BAD_LEN;
-               goto ofp_error;
-       }
-
-       /* Validate that the OXM are in-place and correct. */
-       if (swofp_validate_flow_match(om, &error)) {
-               etype = OFP_ERRTYPE_BAD_MATCH;
-               goto ofp_error;
-       }
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if ((ofm->fm_table_id != OFP_TABLE_ID_ALL) &&
-                   (ofm->fm_table_id != swft->swft_table_id))
-                       continue;
-
-               swofp_flow_delete_on_table(sc, swft, om,
-                   ntohs(ofm->fm_priority),
-                   be64toh(ofm->fm_cookie),
-                   be64toh(ofm->fm_cookie_mask),
-                   ntohl(ofm->fm_out_port),
-                   ntohl(ofm->fm_out_group), strict);
-       }
-
-       m_freem(m);
-       return (0);
-
- ofp_error:
-       swofp_send_error(sc, m, etype, error);
-       return (-1);
-}
-
-int
-swofp_flow_mod_cmd_delete(struct switch_softc *sc, struct mbuf *m)
-{
-       return swofp_flow_mod_cmd_common_delete(sc, m, 0);
-}
-
-int
-swofp_flow_mod_cmd_delete_strict(struct switch_softc *sc, struct mbuf *m)
-{
-       return swofp_flow_mod_cmd_common_delete(sc, m, 1);
-}
-
-ofp_msg_handler *
-swofp_flow_mod_lookup_handler(uint8_t cmd)
-{
-       if (cmd >= nitems(ofp_flow_mod_table))
-               return (NULL);
-       else
-               return (&ofp_flow_mod_table[cmd].ofm_cmd_handler);
-}
-
-int
-swofp_flow_mod(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_flow_mod     *ofm;
-       ofp_msg_handler         *handler;
-       uint16_t                 ohlen;
-
-       ofm = mtod(m, struct ofp_flow_mod *);
-       ohlen = ntohs(ofm->fm_oh.oh_length);
-       if (ohlen < sizeof(*ofm) ||
-           ohlen < (sizeof(*ofm) + ntohs(ofm->fm_match.om_length))) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (-1);
-       }
-
-       handler = swofp_flow_mod_lookup_handler(ofm->fm_command);
-       if (handler) {
-               (*handler)(sc, m);
-       } else {
-               swofp_send_error(sc, m, OFP_ERRTYPE_FLOW_MOD_FAILED,
-                                OFP_ERRFLOWMOD_BAD_COMMAND);
-       }
-
-       return (0);
-}
-
-int
-swofp_group_mod_add(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct ofp_group_mod            *ogm;
-       struct swofp_group_entry        *swge;
-       uint16_t                         error, etype;
-
-       etype = OFP_ERRTYPE_GROUP_MOD_FAILED;
-       ogm = mtod(m, struct ofp_group_mod *);
-
-       if (ofs->swofs_group_table_num >= ofs->swofs_group_max_table) {
-               error = OFP_ERRGROUPMOD_OUT_OF_GROUPS;
-               goto failed;
-       }
-
-       if (ntohl(ogm->gm_group_id) > OFP_GROUP_ID_MAX) {
-               error = OFP_ERRGROUPMOD_INVALID_GROUP;
-               goto failed;
-       }
-
-       if ((swge = swofp_group_entry_lookup(sc,
-           ntohl(ogm->gm_group_id)))) {
-               error = OFP_ERRGROUPMOD_GROUP_EXISTS;
-               goto failed;
-       }
-
-       if (ogm->gm_type != OFP_GROUP_T_ALL) {
-               /* support ALL group only now*/
-               error = OFP_ERRGROUPMOD_BAD_TYPE;
-               goto failed;
-       }
-
-       if (swofp_validate_buckets(sc, m, ogm->gm_type, &etype, &error))
-               goto failed;
-
-       if ((swge = malloc(sizeof(*swge), M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
-               error = OFP_ERRGROUPMOD_UNKNOWN_GROUP;
-               goto failed;
-       }
-
-       swge->swge_group_id = ntohl(ogm->gm_group_id);
-       swge->swge_type = ogm->gm_type;
-
-       swge->swge_buckets_len = (ntohs(ogm->gm_oh.oh_length) -
-           offsetof(struct ofp_group_mod, gm_buckets));
-
-       if (swge->swge_buckets_len > 0) {
-               if ((swge->swge_buckets = malloc(swge->swge_buckets_len,
-                   M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
-                       free(swge, M_DEVBUF, sizeof(*swge));
-                       error = OFP_ERRGROUPMOD_UNKNOWN_GROUP;
-                       goto failed;
-               }
-
-               m_copydata(m, offsetof(struct ofp_group_mod, gm_buckets),
-                   swge->swge_buckets_len, swge->swge_buckets);
-       }
-
-       swofp_group_entry_add(sc, swge);
-
-       m_freem(m);
-       return (0);
-
- failed:
-       swofp_send_error(sc, m, etype, error);
-       return (0);
-}
-
-int
-swofp_group_mod_modify(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_group_mod            *ogm;
-       struct swofp_group_entry        *swge;
-       uint16_t                         error, etype;
-       uint32_t                         obucketlen;
-
-       etype = OFP_ERRTYPE_GROUP_MOD_FAILED;
-       ogm = mtod(m, struct ofp_group_mod *);
-
-       if (ogm->gm_type != OFP_GROUP_T_ALL) {
-               /* support ALL group only now */
-               error = OFP_ERRGROUPMOD_BAD_TYPE;
-               goto failed;
-       }
-
-       if ((swge = swofp_group_entry_lookup(sc,
-           ntohl(ogm->gm_group_id))) == NULL) {
-               error = OFP_ERRGROUPMOD_UNKNOWN_GROUP;
-               goto failed;
-       }
-
-       if (swofp_validate_buckets(sc, m, ogm->gm_type, &etype, &error))
-               goto failed;
-
-       swge->swge_type = ogm->gm_type;
-
-       obucketlen = swge->swge_buckets_len;
-       swge->swge_buckets_len = (ntohs(ogm->gm_oh.oh_length) -
-           offsetof(struct ofp_group_mod, gm_buckets));
-
-       if (obucketlen != swge->swge_buckets_len) {
-               free(swge->swge_buckets, M_DEVBUF, obucketlen);
-               swge->swge_buckets = NULL;
-
-               if (swge->swge_buckets_len > 0 &&
-                   (swge->swge_buckets = malloc(swge->swge_buckets_len,
-                   M_DEVBUF, M_NOWAIT|M_ZERO)) == NULL) {
-                       free(swge, M_DEVBUF, sizeof(*swge));
-                       error = OFP_ERRGROUPMOD_UNKNOWN_GROUP;
-                       goto failed;
-               }
-       }
-
-       if (swge->swge_buckets != NULL)
-               m_copydata(m, offsetof(struct ofp_group_mod, gm_buckets),
-                   swge->swge_buckets_len, swge->swge_buckets);
-
-       m_freem(m);
-       return (0);
-failed:
-       swofp_send_error(sc, m, etype, error);
-       return (0);
-}
-
-int
-swofp_group_mod_delete(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_group_mod            *ogm;
-       struct swofp_group_entry        *swge;
-       int                              group_id;
-
-       ogm = mtod(m, struct ofp_group_mod *);
-       group_id = ntohl(ogm->gm_group_id);
-
-       if (group_id == OFP_GROUP_ID_ALL)
-               swofp_group_entry_delete_all(sc);
-       else if ((swge = swofp_group_entry_lookup(sc, group_id)) != NULL)
-               swofp_group_entry_delete(sc, swge);
-       else {
-               swofp_send_error(sc, m, OFP_ERRTYPE_GROUP_MOD_FAILED,
-                   OFP_ERRGROUPMOD_UNKNOWN_GROUP);
-               return (0);
-       }
-
-       m_freem(m);
-       return (0);
-}
-
-int
-swofp_group_mod(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_group_mod    *ogm;
-       uint16_t                 cmd;
-
-       ogm = mtod(m, struct ofp_group_mod *);
-       if (ntohs(ogm->gm_oh.oh_length) < sizeof(*ogm)) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (-1);
-       }
-
-       cmd = ntohs(ogm->gm_command);
-
-       switch (cmd) {
-       case OFP_GROUPCMD_ADD:
-               return swofp_group_mod_add(sc, m);
-       case OFP_GROUPCMD_MODIFY:
-               return swofp_group_mod_modify(sc, m);
-       case OFP_GROUPCMD_DELETE:
-               return swofp_group_mod_delete(sc, m);
-       default:
-               swofp_send_error(sc, m, OFP_ERRTYPE_GROUP_MOD_FAILED,
-                   OFP_ERRGROUPMOD_BAD_COMMAND);
-               break;
-       }
-
-       return (0);
-}
-
-
-
-/*
- * OpenFlow protocol PACKET OUT message handler
- */
-int
-swofp_recv_packet_out(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_packet_out           *pout;
-       struct ofp_action_header        *ah;
-       struct mbuf                     *mc = NULL, *mcn;
-       int                              al_start, al_len, off;
-       uint16_t                         ohlen, error;
-       struct switch_flow_classify      swfcl = {};
-       struct swofp_pipeline_desc       swpld = { .swpld_swfcl = &swfcl };
-
-       pout = mtod(m, struct ofp_packet_out *);
-       ohlen = ntohs(pout->pout_oh.oh_length);
-       if (ohlen < sizeof(*pout) ||
-           ohlen < (sizeof(*pout) + ntohs(pout->pout_actions_len))) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (-1);
-       }
-
-       al_len = ntohs(pout->pout_actions_len);
-       al_start = offsetof(struct ofp_packet_out, pout_actions);
-
-       /* Validate actions before anything else. */
-       ah = (struct ofp_action_header *)
-           ((uint8_t *)pout + sizeof(*pout));
-       if (swofp_validate_action(sc, ah, al_len, &error)) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_ACTION, error);
-               return (EINVAL);
-       }
-
-       if (pout->pout_buffer_id == OFP_PKTOUT_NO_BUFFER) {
-               /*
-                * It's not necessary to deep copy at here because it's done
-                * in m_dup_pkt().
-                */
-               if ((mc = m_split(m, (al_start + al_len), M_NOWAIT)) == NULL) {
-                       m_freem(m);
-                       return (ENOBUFS);
-               }
-
-               mcn = m_dup_pkt(mc, ETHER_ALIGN, M_NOWAIT);
-               m_freem(mc);
-               if (mcn == NULL) {
-                       m_freem(m);
-                       return (ENOBUFS);
-               }
-
-               mc = mcn;
-       } else {
-               /* TODO We don't do buffering yet. */
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BUFFER_UNKNOWN);
-               return (0);
-       }
-
-       mc = switch_flow_classifier(mc, pout->pout_in_port, &swfcl);
-       if (mc == NULL) {
-               m_freem(m);
-               return (0);
-       }
-
-       TAILQ_INIT(&swpld.swpld_fwdp_q);
-       swfcl.swfcl_in_port = ntohl(pout->pout_in_port);
-       for (off = al_start; off < al_start + al_len;
-           off += ntohs(ah->ah_len)) {
-               ah = (struct ofp_action_header *)(mtod(m, caddr_t) + off);
-
-               mc = swofp_execute_action(sc, mc, &swpld, ah);
-               if (mc == NULL)
-                       break;
-       }
-
-       if (mc)
-               switch_port_egress(sc, &swpld.swpld_fwdp_q, mc);
-
-       m_freem(m);
-
-       return (0);
-}
-
-/*
- * OpenFlow protocol MULTIPART message:
- *
- *  Multipart messages are used to carry a large amount of data because a single
- *  OpenFlow message is limited to 64KB. If a message is over 64KB, it is
- *  splited some OpenFlow messages. OpenFlow Switch Specification says that
- *  "NO OBJECT CAN BE SPLIT ACROSS TWO MESSAGES". In other words, point of
- *  splittig is different per reply, so switch(4) builds multipart message using
- *  swofp_mpms_* functions which splits messages not to object across
- *  two messages.
- */
-int
-swofp_mpmsg_reply_create(struct ofp_multipart *req, struct swofp_mpmsg *swmp)
-{
-       struct mbuf             *hdr, *body;
-       struct ofp_multipart    *omp;
-
-       memset(swmp, 0, sizeof(*swmp));
-
-       ml_init(&swmp->swmp_body);
-
-       MGETHDR(hdr, M_DONTWAIT, MT_DATA);
-       if (hdr == NULL)
-               goto error;
-
-       memset(mtod(hdr, caddr_t), 0, sizeof(*omp));
-       omp = mtod(hdr, struct ofp_multipart *);
-       omp->mp_oh.oh_version = req->mp_oh.oh_version;
-       omp->mp_oh.oh_xid = req->mp_oh.oh_xid;
-       omp->mp_oh.oh_type = OFP_T_MULTIPART_REPLY;
-       omp->mp_type = req->mp_type;
-       hdr->m_len = hdr->m_pkthdr.len = sizeof(*omp);
-       swmp->swmp_hdr = hdr;
-
-       MGETHDR(body, M_DONTWAIT, MT_DATA);
-       if (body == NULL)
-               goto error;
-       MCLGET(body, M_DONTWAIT);
-       if ((body->m_flags & M_EXT) == 0) {
-               m_freem(body);
-               goto error;
-       }
-       body->m_len = body->m_pkthdr.len = 0;
-
-       ml_enqueue(&swmp->swmp_body, body);
-
-       return (0);
-
- error:
-       m_freem(hdr);
-       swmp->swmp_hdr = NULL;
-       return (ENOBUFS);
-}
-
-/*
- * Copy data from a buffer back into the indicated swmp's body buffer
- */
-int
-swofp_mpmsg_put(struct swofp_mpmsg *swmp, caddr_t data, size_t len)
-{
-       struct mbuf     *m, *n;
-       int              error;
-
-       KASSERT(swmp->swmp_hdr != NULL);
-
-       m = swmp->swmp_body.ml_tail;
-       if (m == NULL)
-               return (ENOBUFS);
-
-       if (m->m_pkthdr.len + len > SWOFP_MPMSG_MAX) {
-               MGETHDR(n, M_DONTWAIT, MT_DATA);
-               if (n == NULL)
-                       return (ENOBUFS);
-               MCLGET(n, M_DONTWAIT);
-               if ((n->m_flags & M_EXT) == 0) {
-                       m_freem(n);
-                       return (ENOBUFS);
-               }
-               n->m_len = n->m_pkthdr.len = 0;
-
-               ml_enqueue(&swmp->swmp_body, n);
-
-               m = n;
-       }
-
-       if ((error = m_copyback(m, m->m_pkthdr.len, len, data, M_NOWAIT)))
-               return (error);
-
-       return (0);
-}
-
-/*
- * Copy data from a mbuf back into the indicated swmp's body buffer
- */
-int
-swofp_mpmsg_m_put(struct swofp_mpmsg *swmp, struct mbuf *msg)
-{
-       struct mbuf     *m, *n;
-       int              len;
-
-       KASSERT(swmp->swmp_hdr != NULL);
-
-       m = swmp->swmp_body.ml_tail;
-       if (m == NULL)
-               return (ENOBUFS);
-
-       if (m->m_pkthdr.len + msg->m_pkthdr.len > SWOFP_MPMSG_MAX) {
-               MGETHDR(n, M_DONTWAIT, MT_DATA);
-               if (n == NULL)
-                       return (ENOBUFS);
-               MCLGET(n, M_DONTWAIT);
-               if ((n->m_flags & M_EXT) == 0) {
-                       m_freem(n);
-                       return (ENOBUFS);
-               }
-               n->m_len = n->m_pkthdr.len = 0;
-
-               ml_enqueue(&swmp->swmp_body, n);
-
-               m = n;
-       }
-
-       len = m->m_pkthdr.len + msg->m_pkthdr.len;
-       m_cat(m, msg);
-       m->m_pkthdr.len = len;
-
-       return (0);
-}
-
-void
-swofp_mpmsg_destroy(struct swofp_mpmsg *swmp)
-{
-       m_freem(swmp->swmp_hdr);
-       ml_purge(&swmp->swmp_body);
-}
-
-int
-swofp_multipart_req(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_multipart    *omp;
-       ofp_msg_handler          handler;
-
-       omp = mtod(m, struct ofp_multipart *);
-       if (ntohs(omp->mp_oh.oh_length) < sizeof(*omp)) {
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_BAD_LEN);
-               return (-1);
-       }
-
-       if (omp->mp_flags & OFP_T_MULTIPART_REQUEST) {
-               /* multipart message re-assembly iss not supported yet */
-               m_freem(m);
-               return (ENOBUFS);
-       }
-
-       handler = swofp_lookup_mpmsg_handler(ntohs(omp->mp_type));
-       if (handler)
-               (*handler)(sc, m);
-       else
-               swofp_send_error(sc, m, OFP_ERRTYPE_BAD_REQUEST,
-                   OFP_ERRREQ_MULTIPART);
-
-       return (0);
-}
-
-int
-swofp_multipart_reply(struct switch_softc *sc, struct swofp_mpmsg *swmp)
-{
-       struct ofp_multipart    *omp;
-       struct mbuf             *hdr, *body;
-       int                      len, error = 0;
-
-       KASSERT(swmp->swmp_hdr != NULL);
-
-       omp = mtod(swmp->swmp_hdr, struct ofp_multipart *);
-
-       while ((body = ml_dequeue(&swmp->swmp_body)) != NULL) {
-               omp->mp_oh.oh_length = htons(sizeof(*omp) + body->m_pkthdr.len);
-
-               if (swmp->swmp_body.ml_tail != NULL) {
-                       omp->mp_flags |= htons(OFP_MP_FLAG_REPLY_MORE);
-                       if ((hdr = m_dup_pkt(swmp->swmp_hdr, 0,
-                           M_WAITOK)) == NULL) {
-                               error = ENOBUFS;
-                               goto error;
-                       }
-               } else {
-                       omp->mp_flags &= ~htons(OFP_MP_FLAG_REPLY_MORE);
-                       hdr = swmp->swmp_hdr;
-               }
-
-               if (body->m_pkthdr.len) {
-                       len = hdr->m_pkthdr.len + body->m_pkthdr.len;
-                       m_cat(hdr, body);
-                       hdr->m_pkthdr.len = len;
-               } else
-                       m_freem(body);
-
-               (void)swofp_output(sc, hdr);
-       }
-
-       return (0);
- error:
-       swofp_mpmsg_destroy(swmp);
-       return (error);
-}
-
-int
-swofp_put_flow(struct mbuf *m, struct swofp_flow_table *swft,
-    struct swofp_flow_entry *swfe)
-{
-       struct ofp_flow_stats   *pofs, ofs;
-       struct timespec          now, duration;
-       const uint8_t            pad_data[OFP_ALIGNMENT] = {};
-       struct mbuf             *n;
-       int                      start, off, error, offp, pad = 0;
-       int                      omlen;
-
-       memset(&ofs, 0, sizeof(ofs));
-
-       ofs.fs_table_id = swft->swft_table_id;
-       nanouptime(&now);
-       timespecsub(&now, &swfe->swfe_installed_time, &duration);
-       ofs.fs_duration_sec = ntohl((int)duration.tv_sec);
-       ofs.fs_priority = htons(swfe->swfe_priority);
-       ofs.fs_idle_timeout = htons(swfe->swfe_idle_timeout);
-       ofs.fs_hard_timeout = htons(swfe->swfe_hard_timeout);
-       ofs.fs_cookie = htobe64(swfe->swfe_cookie);
-       ofs.fs_byte_count = htobe64(swfe->swfe_byte_cnt);
-       ofs.fs_packet_count = htobe64(swfe->swfe_packet_cnt);
-
-       /*
-        * struct ofp_flow_statsu has some fields which is variable length ,
-        * so the length is determined by all fields puts.
-        */
-       start = off = m->m_pkthdr.len;
-
-       /*
-        * Put ofp_flow_stat exclusive ofp_match because ofp_match is put
-        * with ofp_matches
-        */
-       if ((error = m_copyback(m, off, (sizeof(ofs) -
-           sizeof(struct ofp_match)), &ofs, M_NOWAIT)))
-               goto failed;
-       off += (sizeof(ofs) - sizeof(struct ofp_match));
-
-       /*
-        * Put ofp_match include ofp_ox_matches and pad
-        */
-       omlen = ntohs(swfe->swfe_match->om_length);
-       pad = OFP_ALIGN(omlen) - omlen;
-       if ((error = m_copyback(m, off, omlen, swfe->swfe_match, M_NOWAIT)))
-               goto failed;
-       off += omlen;
-       if ((error = m_copyback(m, off, pad, pad_data, M_NOWAIT)))
-               goto failed;
-       off += pad;
-
-       /*
-        * Put instructions
-        */
-       if (swfe->swfe_goto_table) {
-               if ((error = m_copyback(m, off,
-                   ntohs(swfe->swfe_goto_table->igt_len),
-                   swfe->swfe_goto_table, M_NOWAIT)))
-                       goto failed;
-               off += ntohs(swfe->swfe_goto_table->igt_len);
-       }
-       if (swfe->swfe_write_metadata) {
-               if ((error = m_copyback(m, off,
-                   ntohs(swfe->swfe_write_metadata->iwm_len),
-                   swfe->swfe_write_metadata, M_NOWAIT)))
-                       goto failed;
-               off += ntohs(swfe->swfe_write_metadata->iwm_len);
-       }
-       if (swfe->swfe_apply_actions) {
-               if ((error = m_copyback(m, off,
-                   ntohs(swfe->swfe_apply_actions->ia_len),
-                   swfe->swfe_apply_actions, M_NOWAIT)))
-                       goto failed;
-               off += ntohs(swfe->swfe_apply_actions->ia_len);
-       }
-       if (swfe->swfe_write_actions) {
-               if ((error = m_copyback(m, off,
-                   ntohs(swfe->swfe_write_actions->ia_len),
-                   swfe->swfe_write_actions, M_NOWAIT)))
-                       goto failed;
-               off += ntohs(swfe->swfe_write_actions->ia_len);
-       }
-       if (swfe->swfe_clear_actions) {
-               if ((error = m_copyback(m, off,
-                   ntohs(swfe->swfe_clear_actions->ia_len),
-                   swfe->swfe_clear_actions, M_NOWAIT)))
-                       goto failed;
-               off += ntohs(swfe->swfe_clear_actions->ia_len);
-       }
-
-       /*
-        * Set ofp_flow_stat length
-        */
-       if ((n = m_pulldown(m, start, sizeof(*pofs), &offp)) == NULL)
-               return (ENOBUFS);
-       pofs = (struct ofp_flow_stats *)(mtod(n, caddr_t) + offp);
-       pofs->fs_length = htons(off - start);
-
-       return (0);
-
- failed:
-       m_freem(m);
-       return (error);
-}
-
-int
-swofp_mp_recv_desc(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_desc          od;
-       struct swofp_mpmsg       swmp;
-       int                      error;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-       memset(&od, 0, sizeof(od));
-
-       strlcpy(od.d_mfr_desc, "openbsd.org", OFP_DESC_STR_LEN);
-       strlcpy(od.d_hw_desc, "openbsd", OFP_DESC_STR_LEN);
-       strlcpy(od.d_sw_desc, "openbsd", OFP_DESC_STR_LEN);
-       strlcpy(od.d_serial_num, "0", OFP_SERIAL_NUM_LEN);
-       strlcpy(od.d_dp_desc, sc->sc_if.if_xname, OFP_DESC_STR_LEN);
-
-       if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&od, sizeof(od))))
-               goto failed;
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_put_flows_from_table(struct swofp_mpmsg *swmp,
-    struct swofp_flow_table *swft, struct ofp_flow_stats_request *ofsr)
-{
-       struct swofp_flow_entry *swfe;
-       struct mbuf             *m;
-       int                      error = 0;
-
-       LIST_FOREACH(swfe, &swft->swft_flow_list, swfe_next) {
-               if (!swofp_flow_cmp_non_strict(swfe, &ofsr->fsr_match))
-                       continue;
-
-               if (!swofp_flow_filter(swfe, be64toh(ofsr->fsr_cookie),
-                   be64toh(ofsr->fsr_cookie_mask), ntohl(ofsr->fsr_out_port),
-                   ntohl(ofsr->fsr_out_group)))
-                       continue;
-
-               MGETHDR(m, M_DONTWAIT, MT_DATA);
-               if (m == NULL)
-                       return (ENOBUFS);
-               m->m_len = m->m_pkthdr.len = 0;
-
-               if ((error = swofp_put_flow(m, swft, swfe)))
-                       break;
-
-               if ((error = swofp_mpmsg_m_put(swmp, m))) {
-                       /* swofp_mpmsg_m_put() doesn't free m on error */
-                       m_freem(m);
-                       break;
-               }
-       }
-
-       return (error);
-}
-
-int
-swofp_mp_recv_flow(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct ofp_flow_stats_request   *ofsr;
-       struct swofp_flow_table         *swft;
-       struct swofp_mpmsg               swmp;
-       int                              error;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-       ofsr = (struct ofp_flow_stats_request *)
-           (mtod(m, caddr_t) + sizeof(struct ofp_multipart));
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if ((ofsr->fsr_table_id != OFP_TABLE_ID_ALL) &&
-                   (ofsr->fsr_table_id != swft->swft_table_id))
-                       continue;
-
-               if ((error = swofp_put_flows_from_table(&swmp, swft, ofsr)))
-                       goto failed;
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-void
-swofp_aggregate_stat_from_table(struct ofp_aggregate_stats *aggstat,
-    struct swofp_flow_table *swft, struct ofp_aggregate_stats_request *oasr)
-{
-       struct swofp_flow_entry *swfe;
-       uint64_t                 packet_cnt = 0, byte_cnt = 0;
-       uint32_t                 flow_cnt = 0;
-
-       LIST_FOREACH(swfe, &swft->swft_flow_list, swfe_next) {
-               if (!swofp_flow_cmp_non_strict(swfe, &oasr->asr_match))
-                       continue;
-
-               if (!swofp_flow_filter(swfe, be64toh(oasr->asr_cookie),
-                   be64toh(oasr->asr_cookie_mask), ntohl(oasr->asr_out_port),
-                   ntohl(oasr->asr_out_group)))
-                       continue;
-
-               packet_cnt += swfe->swfe_packet_cnt;
-               byte_cnt += swfe->swfe_byte_cnt;
-               flow_cnt++;
-       }
-
-       aggstat->as_packet_count = htobe64(packet_cnt);
-       aggstat->as_byte_count = htobe64(byte_cnt);
-       aggstat->as_flow_count = htonl(flow_cnt++);
-}
-
-int
-swofp_mp_recv_aggregate_flow_stat(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                        *ofs = sc->sc_ofs;
-       struct ofp_aggregate_stats_request      *oasr;
-       struct swofp_flow_table                 *swft;
-       struct swofp_mpmsg                       swmp;
-       struct ofp_aggregate_stats               aggstat;
-       int                                      error;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-       memset(&aggstat, 0, sizeof(aggstat));
-
-       oasr = (struct ofp_aggregate_stats_request *)
-           (mtod(m, caddr_t) + sizeof(struct ofp_multipart));
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               if ((oasr->asr_table_id != OFP_TABLE_ID_ALL) &&
-                   (oasr->asr_table_id != swft->swft_table_id))
-                       continue;
-               swofp_aggregate_stat_from_table(&aggstat, swft, oasr);
-       }
-
-       if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&aggstat,
-           sizeof(aggstat))))
-               goto failed;
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_mp_recv_table_stats(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs        *ofs = sc->sc_ofs;
-       struct ofp_table_stats   tblstat;
-       struct swofp_flow_table *swft;
-       struct swofp_mpmsg       swmp;
-       int                      error;
-
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               memset(&tblstat, 0, sizeof(tblstat));
-
-               tblstat.ts_table_id = swft->swft_table_id;
-               tblstat.ts_active_count = htonl((uint32_t)swft->swft_flow_num);
-               tblstat.ts_lookup_count = htobe64(swft->swft_lookup_count);
-               tblstat.ts_matched_count = htobe64(swft->swft_matched_count);
-
-               if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&tblstat,
-                   sizeof(tblstat))))
-                       goto failed;
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_mp_recv_port_stats(struct switch_softc *sc, struct mbuf *m)
-{
-       struct switch_port      *swpo;
-       struct swofp_mpmsg       swmp;
-       struct ifnet            *ifs;
-       struct ofp_port_stats    postat;
-       int                      error;
-       struct timespec          now, duration;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-       nanouptime(&now);
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-               memset(&postat, 0, sizeof(postat));
-               ifs = if_get(swpo->swpo_ifindex);
-               if (ifs == NULL)
-                       continue;
-
-               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);
-               postat.pt_tx_bytes = htobe64(ifs->if_ibytes);
-               postat.pt_rx_dropped = htobe64(ifs->if_iqdrops);
-               postat.pt_tx_dropped = htobe64(ifs->if_oqdrops);
-               postat.pt_rx_errors = htobe64(ifs->if_ierrors);
-               postat.pt_tx_errors = htobe64(ifs->if_oerrors);
-               postat.pt_rx_frame_err = htobe64(0);
-               postat.pt_rx_over_err = htobe64(0);
-               postat.pt_rx_crc_err = htobe64(0);
-               postat.pt_collision = htobe64(ifs->if_collisions);
-               timespecsub(&now, &swpo->swpo_appended, &duration);
-               postat.pt_duration_sec = htonl((uint32_t)duration.tv_sec);
-               postat.pt_duration_nsec = htonl(duration.tv_nsec);
-
-               if_put(ifs);
-
-               if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&postat,
-                   sizeof(postat))))
-                       goto failed;
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_table_features_put_oxm(struct mbuf *m, int *off, uint16_t tp_type)
-{
-       struct ofp_table_feature_property        tp;
-       struct ofp_ox_match                      oxm;
-       uint32_t                                 padding = 0;
-       int                                      i, supported = 0;
-
-       for (i = 0 ; i < nitems(ofp_oxm_handlers); i++) {
-               switch (tp_type) {
-               case OFP_TABLE_FEATPROP_MATCH:
-                       if (ofp_oxm_handlers[i].oxm_match == NULL)
-                               continue;
-                       break;
-               case OFP_TABLE_FEATPROP_WILDCARDS:
-                       if (ofp_oxm_handlers[i].oxm_match == NULL ||
-                           !(ofp_oxm_handlers[i].oxm_flags &
-                           SWOFP_MATCH_WILDCARD))
-                               continue;
-                       break;
-               case OFP_TABLE_FEATPROP_APPLY_SETFIELD:
-               case OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS:
-               case OFP_TABLE_FEATPROP_WRITE_SETFIELD:
-               case OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS:
-                       if (ofp_oxm_handlers[i].oxm_set == NULL)
-                               continue;
-                       break;
-               }
-               supported++;
-       }
-
-       tp.tp_type = htons(tp_type);
-       tp.tp_length = htons((sizeof(oxm) * supported) + sizeof(tp));
-
-       if (m_copyback(m, *off, sizeof(tp), (caddr_t)&tp, M_NOWAIT))
-               return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-       *off += sizeof(tp);
-
-       for (i = 0 ; i < nitems(ofp_oxm_handlers); i++) {
-               switch (tp_type) {
-               case OFP_TABLE_FEATPROP_MATCH:
-                       if (ofp_oxm_handlers[i].oxm_match == NULL)
-                               continue;
-                       break;
-               case OFP_TABLE_FEATPROP_WILDCARDS:
-                       if (ofp_oxm_handlers[i].oxm_match == NULL ||
-                           !(ofp_oxm_handlers[i].oxm_flags &
-                           SWOFP_MATCH_WILDCARD))
-                               continue;
-                       break;
-               case OFP_TABLE_FEATPROP_APPLY_SETFIELD:
-               case OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS:
-               case OFP_TABLE_FEATPROP_WRITE_SETFIELD:
-               case OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS:
-                       if (ofp_oxm_handlers[i].oxm_set == NULL)
-                               continue;
-                       break;
-               }
-
-               memset(&oxm, 0, sizeof(oxm));
-               OFP_OXM_SET_FIELD(&oxm, ofp_oxm_handlers[i].oxm_field);
-               if ((tp_type == OFP_TABLE_FEATPROP_MATCH) &&
-                   (ofp_oxm_handlers[i].oxm_flags & SWOFP_MATCH_MASK))
-                       OFP_OXM_SET_HASMASK(&oxm);
-               oxm.oxm_class = htons(OFP_OXM_C_OPENFLOW_BASIC);
-               oxm.oxm_length = ofp_oxm_handlers[i].oxm_len;
-
-               if (m_copyback(m, *off, sizeof(oxm), (caddr_t)&oxm, M_NOWAIT))
-                       return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-               *off += sizeof(oxm);
-       }
-
-       /*
-        * It's always 4 byte for padding because struct ofp_ox_mach and
-        * struct ofp_table_feature_property are 4 byte.
-        */
-       if ((supported & 0x1) == 0) {
-               if (m_copyback(m, *off, sizeof(padding),
-                   (caddr_t)&padding, M_NOWAIT))
-                       return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-               *off += sizeof(padding);
-       }
-
-       return (0);
-}
-
-int
-swofp_table_features_put_actions(struct mbuf *m, int *off, uint16_t tp_type)
-{
-       struct ofp_table_feature_property        tp;
-       struct ofp_action_header                 action;
-       int                                      i, supported = 0;
-       int                                      actionlen, padsize;
-       uint8_t                                  padding[8];
-
-       for (i = 0 ; i < nitems(ofp_action_handlers); i++) {
-               if (ofp_action_handlers[i].action)
-                       supported++;
-       }
-
-       actionlen = sizeof(action) - sizeof(action.ah_pad);
-       tp.tp_type = htons(tp_type);
-       tp.tp_length = (actionlen * supported) + sizeof(tp);
-
-       padsize = OFP_ALIGN(tp.tp_length) - tp.tp_length;
-       tp.tp_length = htons(tp.tp_length);
-
-       if (m_copyback(m, *off, sizeof(tp), (caddr_t)&tp, M_NOWAIT))
-               return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-       *off += sizeof(tp);
-
-       for (i = 0 ; i < nitems(ofp_action_handlers); i++) {
-               if (ofp_action_handlers[i].action == NULL)
-                       continue;
-
-               memset(&action, 0, actionlen);
-               action.ah_type = ntohs(ofp_action_handlers[i].action_type);
-               /* XXX action length is different for experimenter type. */
-               action.ah_len = ntohs(actionlen);
-
-               if (m_copyback(m, *off, actionlen,
-                   (caddr_t)&action, M_NOWAIT))
-                       return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-               *off += actionlen;
-       }
-
-       if (padsize) {
-               memset(padding, 0, padsize);
-               if (m_copyback(m, *off, padsize, &padding, M_NOWAIT))
-                       return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-
-               *off += padsize;
-       }
-
-       return (0);
-}
-
-int
-swofp_table_features_put_instruction(struct mbuf *m, int *off, uint16_t tp_type)
-{
-       struct ofp_table_feature_property        tp;
-       struct ofp_instruction                   instructions[] =
-           {
-               {
-                       htons(OFP_INSTRUCTION_T_GOTO_TABLE),
-                       htons(sizeof(struct ofp_instruction))
-               },
-               {
-                       htons(OFP_INSTRUCTION_T_WRITE_META),
-                       htons(sizeof(struct ofp_instruction))
-               },
-               {
-                       htons(OFP_INSTRUCTION_T_WRITE_ACTIONS),
-                       htons(sizeof(struct ofp_instruction))
-               },
-               {
-                       htons(OFP_INSTRUCTION_T_APPLY_ACTIONS),
-                       htons(sizeof(struct ofp_instruction))
-               },
-               {
-                       htons(OFP_INSTRUCTION_T_CLEAR_ACTIONS),
-                       htons(sizeof(struct ofp_instruction))
-               },
-           };
-
-       tp.tp_type = htons(tp_type);
-       tp.tp_length = htons(sizeof(instructions) + sizeof(tp));
-
-       if (m_copyback(m, *off, sizeof(tp), (caddr_t)&tp, M_NOWAIT))
-               return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-       *off += sizeof(tp);
-
-       if (m_copyback(m, *off, sizeof(instructions),
-           (caddr_t)instructions, M_NOWAIT))
-               return (OFP_ERRREQ_MULTIPART_OVERFLOW);
-       *off += sizeof(instructions);
-
-       return (0);
-}
-
-int
-swofp_mp_recv_table_features(struct switch_softc *sc, struct mbuf *m)
-{
-       struct swofp_ofs                *ofs = sc->sc_ofs;
-       struct swofp_flow_table         *swft;
-       struct ofp_table_features       *tblf;
-       struct mbuf                     *n;
-       int                              off, error;
-       struct swofp_mpmsg               swmp;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto error;
-
-       TAILQ_FOREACH(swft, &ofs->swofs_table_list, swft_table_next) {
-               /* using mbuf because table features struct is variable length*/
-               MGETHDR(n, M_DONTWAIT, MT_DATA);
-               if (n == NULL)
-                       goto error;
-               MCLGET(n, M_DONTWAIT);
-               if ((n->m_flags & M_EXT) == 0) {
-                       m_freem(n);
-                       goto error;
-               }
-               n->m_len = n->m_pkthdr.len = sizeof(*tblf);
-
-               tblf = mtod(n, struct ofp_table_features *);
-               memset(tblf, 0, sizeof(*tblf));
-               tblf->tf_tableid = swft->swft_table_id;
-               tblf->tf_metadata_match = UINT64_MAX;
-               tblf->tf_metadata_write = UINT64_MAX;
-               tblf->tf_config = 0;
-               tblf->tf_max_entries = htonl(ofs->swofs_flow_max_entry);
-
-               off = sizeof(*tblf);
-               if ((error = swofp_table_features_put_instruction(n, &off,
-                   OFP_TABLE_FEATPROP_INSTRUCTION)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_instruction(n, &off,
-                   OFP_TABLE_FEATPROP_INSTRUCTION_MISS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_actions(n, &off,
-                   OFP_TABLE_FEATPROP_APPLY_ACTIONS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_actions(n, &off,
-                   OFP_TABLE_FEATPROP_APPLY_ACTIONS_MISS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_actions(n, &off,
-                   OFP_TABLE_FEATPROP_WRITE_ACTIONS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_actions(n, &off,
-                   OFP_TABLE_FEATPROP_WRITE_ACTIONS_MISS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_MATCH)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_WILDCARDS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_WRITE_SETFIELD)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_WRITE_SETFIELD_MISS)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_APPLY_SETFIELD)))
-                       goto error;
-
-               if ((error = swofp_table_features_put_oxm(n, &off,
-                   OFP_TABLE_FEATPROP_APPLY_SETFIELD_MISS)))
-                       goto error;
-
-               tblf->tf_length = htons(n->m_pkthdr.len);
-
-               if ((error = swofp_mpmsg_m_put(&swmp, n))) {
-                       m_freem(n);
-                       goto error;
-               }
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- error:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_mp_recv_port_desc(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_switch_port   swp;
-       struct switch_port      *swpo;
-       struct swofp_mpmsg       swmp;
-       struct ifnet            *ifs;
-       int                      error;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp))) {
-               m_freem(m);
-               return (error);
-       }
-
-       TAILQ_FOREACH(swpo, &sc->sc_swpo_list, swpo_list_next) {
-               memset(&swp, 0, sizeof(swp));
-               ifs = if_get(swpo->swpo_ifindex);
-               if (ifs == NULL)
-                       continue;
-
-               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);
-               strlcpy(swp.swp_name, ifs->if_xname,
-                   sizeof(swp.swp_name));
-
-               if (!ISSET(ifs->if_flags, IFF_UP))
-                       swp.swp_config |= OFP_PORTCONFIG_PORT_DOWN;
-               if (!ISSET(swpo->swpo_flags, IFBIF_STP))
-                       swp.swp_config |= OFP_PORTCONFIG_NO_STP;
-               swp.swp_config = htonl(swp.swp_config);
-
-               if (!LINK_STATE_IS_UP(ifs->if_data.ifi_link_state))
-                       swp.swp_state |= OFP_PORTSTATE_LINK_DOWN;
-
-               if_put(ifs);
-
-               swp.swp_state = htonl(swp.swp_state);
-               /* XXX how to get the if_media from ifp? ioctl? */
-               swp.swp_cur = htonl(swp.swp_cur);
-               swp.swp_advertised = htonl(swp.swp_advertised);
-               swp.swp_supported = htonl(swp.swp_supported);
-               swp.swp_peer = htonl(swp.swp_peer);
-
-               if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&swp,
-                   sizeof(swp))))
-                       goto error;
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- error:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_mp_recv_group_desc(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_group_desc            ogd;
-       struct swofp_group_entry        *swge;
-       struct swofp_mpmsg               swmp;
-       int                              error;
-
-       if ((error = swofp_mpmsg_reply_create(
-           mtod(m, struct ofp_multipart *), &swmp)))
-               goto failed;
-
-
-       LIST_FOREACH(swge, &sc->sc_ofs->swofs_group_table, swge_next) {
-               memset(&ogd, 0, sizeof(ogd));
-
-               ogd.gd_length = htons(offsetof(struct ofp_group_desc,
-                   gd_buckets) + swge->swge_buckets_len);
-               ogd.gd_group_id = htonl(swge->swge_group_id);
-               ogd.gd_type = swge->swge_type;
-
-               /*
-                * Copy back GROUP DESC without buckets
-                */
-               if ((error = swofp_mpmsg_put(&swmp, (caddr_t)&ogd,
-                   sizeof(ogd))))
-                       goto failed;
-
-               /*
-                * Copy back buckets on GROUP DESC
-                */
-               if (swge->swge_buckets != NULL &&
-                   (error = swofp_mpmsg_put(&swmp, (caddr_t)swge->swge_buckets,
-                   swge->swge_buckets_len)))
-                       goto failed;
-       }
-
-       m_freem(m);
-       return swofp_multipart_reply(sc, &swmp);
-
- failed:
-       m_freem(m);
-       swofp_mpmsg_destroy(&swmp);
-       return (error);
-}
-
-int
-swofp_barrier_req(struct switch_softc *sc, struct mbuf *m)
-{
-       swofp_barrier_reply(sc, m);
-       return 0;
-}
-
-void
-swofp_barrier_reply(struct switch_softc *sc, struct mbuf *m)
-{
-       struct ofp_header       *oh;
-
-       oh = mtod(m, struct ofp_header *);
-       oh->oh_type = OFP_T_BARRIER_REPLY;
-
-       (void)swofp_output(sc, m);
-}
index 1198dd8..e876572 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: sockio.h,v 1.83 2019/11/13 11:54:01 tobhe Exp $       */
+/*     $OpenBSD: sockio.h,v 1.84 2021/11/11 10:03:10 claudio Exp $     */
 /*     $NetBSD: sockio.h,v 1.5 1995/08/23 00:40:47 thorpej Exp $       */
 
 /*-
 #define SIOCBRDGGPARAM  _IOWR('i', 88, struct ifbropreq)/* get brdg STP parms */
 #define SIOCBRDGSTXHC    _IOW('i', 89, struct ifbrparam)/* set tx hold count */
 #define SIOCBRDGSPROTO  _IOW('i', 90, struct ifbrparam)/* set protocol */
-#define SIOCBRDGS
-
-#define        SIOCSWGDPID     _IOWR('i', 91, struct ifbrparam)/* get datapath id */
-#define        SIOCSWSDPID      _IOW('i', 92, struct ifbrparam)/* set datapath id */
-#define        SIOCSWGMAXGROUP _IOWR('i', 93, struct ifbrparam)/* get max groups */
-#define        SIOCSWSPORTNO   _IOWR('i', 95, struct ifbreq)   /* set port number */
-#define        SIOCSWGMAXFLOW  _IOWR('i', 96, struct ifbrparam)/* get max flow per table */
 
 #define        SIOCSIFMTU       _IOW('i', 127, struct ifreq)   /* set ifnet mtu */
 #define        SIOCGIFMTU      _IOWR('i', 126, struct ifreq)   /* get ifnet mtu */