[ovs-dev] [PATCHv5 4/4] ofp-util: Add SCTP support

Joe Stringer joe at wand.net.nz
Thu Aug 22 08:24:45 UTC 2013


Reviewed-by: Simon Horman <horms at verge.net.au>
Signed-off-by: Joe Stringer <joe at wand.net.nz>
---
v5: No change
v4: No change
v3: Rebase
v2: Add flowmod parse tests
    Add set-field tests
    Add NEWS item
    Add sctp to ovs-ofctl.8
---
 NEWS                     |    2 +
 OPENFLOW-1.1+            |    5 ---
 lib/match.c              |    4 ++
 lib/meta-flow.c          |   38 +++++++++++++++++++++++++
 lib/meta-flow.h          |    4 ++
 lib/nx-match.c           |    5 +++
 lib/ofp-parse.c          |    2 +
 lib/ofp-print.c          |    6 ++++
 lib/ofp-util.c           |   10 ++----
 tests/ofp-print.at       |   64 ++++++++++++++++++++++++++++++++++++++++++
 tests/ofproto-dpif.at    |   54 ++++++++++++++++++++++++++++++-----
 tests/ovs-ofctl.at       |   69 ++++++++++++++++++++++++++++++++++++++--------
 tests/test-netflow.c     |    6 ++++
 utilities/ovs-ofctl.8.in |   20 ++++++++----
 14 files changed, 251 insertions(+), 38 deletions(-)

diff --git a/NEWS b/NEWS
index 1246383..2df7b55 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,7 @@
 post-v1.12.0
 ---------------------
+    - OpenFlow:
+      * Support matching, rewriting SCTP ports
 
 
 v1.12.0 - xx xxx xxxx
diff --git a/OPENFLOW-1.1+ b/OPENFLOW-1.1+
index 329c5a2..190dd29 100644
--- a/OPENFLOW-1.1+
+++ b/OPENFLOW-1.1+
@@ -85,11 +85,6 @@ probably incomplete.
       feature.  This is partially merged.
       [optional for OF1.1+]
 
-    * SCTP.  Joe Stringer maintains a patch series that adds this
-      feature.  It has received review comments that need to be
-      addressed before it is merged.
-      [optional for OF1.1+]
-
     * Match and set double-tagged VLANs (QinQ).  This requires kernel
       work for reasonable performance.
       [optional for OF1.1+]
diff --git a/lib/match.c b/lib/match.c
index e97b0b1..c038d48 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -868,6 +868,8 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
                     ds_put_cstr(s, "tcp,");
                 } else if (f->nw_proto == IPPROTO_UDP) {
                     ds_put_cstr(s, "udp,");
+                } else if (f->nw_proto == IPPROTO_SCTP) {
+                    ds_put_cstr(s, "sctp,");
                 } else {
                     ds_put_cstr(s, "ip,");
                     skip_proto = false;
@@ -884,6 +886,8 @@ match_format(const struct match *match, struct ds *s, unsigned int priority)
                     ds_put_cstr(s, "tcp6,");
                 } else if (f->nw_proto == IPPROTO_UDP) {
                     ds_put_cstr(s, "udp6,");
+                } else if (f->nw_proto == IPPROTO_SCTP) {
+                    ds_put_cstr(s, "sctp6,");
                 } else {
                     ds_put_cstr(s, "ipv6,");
                     skip_proto = false;
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index ce061a3..86a7a1d 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -500,6 +500,26 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     },
 
     {
+        MFF_SCTP_SRC, "sctp_src", NULL,
+        MF_FIELD_SIZES(be16),
+        MFM_FULLY,
+        MFS_DECIMAL,
+        MFP_SCTP,
+        true,
+        OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC",
+        OXM_OF_SCTP_SRC, "OXM_OF_SCTP_SRC",
+    }, {
+        MFF_SCTP_DST, "sctp_dst", NULL,
+        MF_FIELD_SIZES(be16),
+        MFM_FULLY,
+        MFS_DECIMAL,
+        MFP_SCTP,
+        true,
+        OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST",
+        OXM_OF_SCTP_DST, "OXM_OF_SCTP_DST",
+    },
+
+    {
         MFF_ICMPV4_TYPE, "icmp_type", NULL,
         MF_FIELD_SIZES(u8),
         MFM_NONE,
@@ -781,11 +801,13 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
         return !wc->masks.tp_src;
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
         return !wc->masks.tp_dst;
@@ -866,6 +888,8 @@ mf_are_prereqs_ok(const struct mf_field *mf, const struct flow *flow)
         return is_ip_any(flow) && flow->nw_proto == IPPROTO_TCP;
     case MFP_UDP:
         return is_ip_any(flow) && flow->nw_proto == IPPROTO_UDP;
+    case MFP_SCTP:
+        return is_ip_any(flow) && flow->nw_proto == IPPROTO_SCTP;
     case MFP_ICMPV4:
         return is_icmpv4(flow);
     case MFP_ICMPV6:
@@ -932,6 +956,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
     case MFF_TCP_DST:
     case MFF_UDP_SRC:
     case MFF_UDP_DST:
+    case MFF_SCTP_SRC:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_TYPE:
@@ -1142,11 +1168,13 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         value->be16 = flow->tp_src;
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         value->be16 = flow->tp_dst;
         break;
 
@@ -1332,11 +1360,13 @@ mf_set_value(const struct mf_field *mf,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         match_set_tp_src(match, value->be16);
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         match_set_tp_dst(match, value->be16);
         break;
 
@@ -1524,11 +1554,13 @@ mf_set_flow_value(const struct mf_field *mf,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         flow->tp_src = value->be16;
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         flow->tp_dst = value->be16;
         break;
 
@@ -1727,6 +1759,7 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
         match->wc.masks.tp_src = htons(0);
@@ -1735,6 +1768,7 @@ mf_set_wild(const struct mf_field *mf, struct match *match)
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
         match->wc.masks.tp_dst = htons(0);
@@ -1901,11 +1935,13 @@ mf_set(const struct mf_field *mf,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         match_set_tp_src_masked(match, value->be16, mask->be16);
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         match_set_tp_dst_masked(match, value->be16, mask->be16);
         break;
 
@@ -2010,6 +2046,8 @@ mf_random_value(const struct mf_field *mf, union mf_value *value)
     case MFF_TCP_DST:
     case MFF_UDP_SRC:
     case MFF_UDP_DST:
+    case MFF_SCTP_SRC:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_TYPE:
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
index 93b894d..969ca9e 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -121,6 +121,9 @@ enum mf_field_id {
     MFF_UDP_SRC,                /* be16 (used for IPv4 or IPv6) */
     MFF_UDP_DST,                /* be16 (used for IPv4 or IPv6) */
 
+    MFF_SCTP_SRC,               /* be16 (used for IPv4 or IPv6) */
+    MFF_SCTP_DST,               /* be16 (used for IPv4 or IPv6) */
+
     MFF_ICMPV4_TYPE,            /* u8 */
     MFF_ICMPV4_CODE,            /* u8 */
 
@@ -190,6 +193,7 @@ enum mf_prereqs {
     /* L2+L3 requirements. */
     MFP_TCP,                    /* On IPv4 or IPv6. */
     MFP_UDP,                    /* On IPv4 or IPv6. */
+    MFP_SCTP,                   /* On IPv4 or IPv6. */
     MFP_ICMPV4,
     MFP_ICMPV6,
 
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 09f7f54..e9b1375 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -535,6 +535,11 @@ nxm_put_ip(struct ofpbuf *b, const struct match *match,
                         flow->tp_src, match->wc.masks.tp_src);
             nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST,
                         flow->tp_dst, match->wc.masks.tp_dst);
+        } else if (flow->nw_proto == IPPROTO_SCTP) {
+            nxm_put_16m(b, OXM_OF_SCTP_SRC, flow->tp_src,
+                        match->wc.masks.tp_src);
+            nxm_put_16m(b, OXM_OF_SCTP_DST, flow->tp_dst,
+                        match->wc.masks.tp_dst);
         } else if (flow->nw_proto == icmp_proto) {
             if (match->wc.masks.tp_src) {
                 nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 2983474..dd0738c 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -1034,11 +1034,13 @@ parse_protocol(const char *name, const struct protocol **p_out)
         { "icmp", ETH_TYPE_IP, IPPROTO_ICMP },
         { "tcp", ETH_TYPE_IP, IPPROTO_TCP },
         { "udp", ETH_TYPE_IP, IPPROTO_UDP },
+        { "sctp", ETH_TYPE_IP, IPPROTO_SCTP },
         { "ipv6", ETH_TYPE_IPV6, 0 },
         { "ip6", ETH_TYPE_IPV6, 0 },
         { "icmp6", ETH_TYPE_IPV6, IPPROTO_ICMPV6 },
         { "tcp6", ETH_TYPE_IPV6, IPPROTO_TCP },
         { "udp6", ETH_TYPE_IPV6, IPPROTO_UDP },
+        { "sctp6", ETH_TYPE_IPV6, IPPROTO_SCTP },
         { "rarp", ETH_TYPE_RARP, 0},
         { "mpls", ETH_TYPE_MPLS, 0 },
         { "mplsm", ETH_TYPE_MPLS_MCAST, 0 },
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 02d4380..23ba9d4 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -74,6 +74,10 @@ ofp_packet_to_string(const void *data, size_t len)
             struct udp_header *uh = buf.l4;
             ds_put_format(&ds, " udp_csum:%"PRIx16,
                           ntohs(uh->udp_csum));
+        } else if (flow.nw_proto == IPPROTO_SCTP) {
+            struct sctp_header *sh = buf.l4;
+            ds_put_format(&ds, " sctp_csum:%"PRIx32,
+                          ntohl(sh->sctp_csum));
         }
     }
 
@@ -649,6 +653,8 @@ ofp10_match_to_string(const struct ofp10_match *om, int verbosity)
                     ds_put_cstr(&f, "tcp,");
                 } else if (om->nw_proto == IPPROTO_UDP) {
                     ds_put_cstr(&f, "udp,");
+                } else if (om->nw_proto == IPPROTO_SCTP) {
+                    ds_put_cstr(&f, "sctp,");
                 } else {
                     ds_put_cstr(&f, "ip,");
                     skip_proto = false;
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 45ff0a1..62cfd2e 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -420,6 +420,7 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
 
         case IPPROTO_TCP:
         case IPPROTO_UDP:
+        case IPPROTO_SCTP:
             if (!(wc & (OFPFW11_TP_SRC))) {
                 match_set_tp_src(match, ofmatch->tp_src);
             }
@@ -428,11 +429,6 @@ ofputil_match_from_ofp11_match(const struct ofp11_match *ofmatch,
             }
             break;
 
-        case IPPROTO_SCTP:
-            /* We don't support SCTP and it seems that we should tell the
-             * controller, since OF1.1 implementations are supposed to. */
-            return OFPERR_OFPBMC_BAD_FIELD;
-
         default:
             /* OF1.1 says explicitly to ignore this. */
             break;
@@ -4835,13 +4831,15 @@ ofputil_normalize_match__(struct match *match, bool may_log)
         may_match = MAY_NW_PROTO | MAY_IPVx | MAY_NW_ADDR;
         if (match->flow.nw_proto == IPPROTO_TCP ||
             match->flow.nw_proto == IPPROTO_UDP ||
+            match->flow.nw_proto == IPPROTO_SCTP ||
             match->flow.nw_proto == IPPROTO_ICMP) {
             may_match |= MAY_TP_ADDR;
         }
     } else if (match->flow.dl_type == htons(ETH_TYPE_IPV6)) {
         may_match = MAY_NW_PROTO | MAY_IPVx | MAY_IPV6;
         if (match->flow.nw_proto == IPPROTO_TCP ||
-            match->flow.nw_proto == IPPROTO_UDP) {
+            match->flow.nw_proto == IPPROTO_UDP ||
+            match->flow.nw_proto == IPPROTO_SCTP) {
             may_match |= MAY_TP_ADDR;
         } else if (match->flow.nw_proto == IPPROTO_ICMPV6) {
             may_match |= MAY_TP_ADDR;
diff --git a/tests/ofp-print.at b/tests/ofp-print.at
index 266af6c..f554aba 100644
--- a/tests/ofp-print.at
+++ b/tests/ofp-print.at
@@ -825,6 +825,36 @@ OFPT_FLOW_MOD (OF1.2) (xid=0x52334507): ADD priority=255,ip actions=set_field:19
 ])
 AT_CLEANUP
 
+AT_SETUP([OFPT_FLOW_MOD - OF1.2 - set-field sctp_src])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
+03 0e 00 58 52 33 45 07 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff \
+ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 \
+00 01 00 0f 80 00 0a 02 08 00 80 00 14 01 84 00 \
+00 04 00 18 00 00 00 00 00 19 00 10 80 00 22 02 \
+0d 06 00 00 00 00 00 00                         \
+" 2], [0], [dnl
+OFPT_FLOW_MOD (OF1.2) (xid=0x52334507): ADD priority=255,sctp actions=set_field:3334->sctp_src
+], [dnl
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_FLOW_MOD - OF1.2 - set-field sctp_dst])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
+03 0e 00 58 52 33 45 07 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff \
+ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00 \
+00 01 00 0f 80 00 0a 02 08 00 80 00 14 01 84 00 \
+00 04 00 18 00 00 00 00 00 19 00 10 80 00 24 02 \
+11 5d 00 00 00 00 00 00                         \
+" 2], [0], [dnl
+OFPT_FLOW_MOD (OF1.2) (xid=0x52334507): ADD priority=255,sctp actions=set_field:4445->sctp_dst
+], [dnl
+])
+AT_CLEANUP
+
 AT_SETUP([OFPT_FLOW reply - OF1.2 - set-field ip_src])
 AT_KEYWORDS([ofp-print])
 AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
@@ -859,6 +889,40 @@ OFPST_FLOW reply (OF1.2) (xid=0x52334509):
 ])
 AT_CLEANUP
 
+AT_SETUP([OFPT_FLOW reply - OF1.2 - set-field sctp_src])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
+03 13 00 68 52 33 45 04 00 01 00 00 00 00 00 00 \
+00 58 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 01 00 0f 80 00 0a 02 08 00 80 00 14 01 84 00 \
+00 04 00 18 00 00 00 00 00 19 00 10 80 00 22 02 \
+0d 06 00 00 00 00 00 00                         \
+" 2], [0], [dnl
+OFPST_FLOW reply (OF1.2) (xid=0x52334504):
+ cookie=0x0, duration=0s, table=0, n_packets=0, n_bytes=0, priority=255,sctp actions=set_field:3334->sctp_src
+], [dnl
+])
+AT_CLEANUP
+
+AT_SETUP([OFPT_FLOW reply - OF1.2 - set-field sctp_dst])
+AT_KEYWORDS([ofp-print])
+AT_CHECK([ovs-ofctl '-vPATTERN:console:%c|%p|%m' ofp-print "\
+03 13 00 68 52 33 45 09 00 01 00 00 00 00 00 00 \
+00 58 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \
+00 01 00 0f 80 00 0a 02 08 00 80 00 14 01 84 00 \
+00 04 00 18 00 00 00 00 00 19 00 10 80 00 24 02 \
+11 5d 00 00 00 00 00 00                         \
+" 2], [0], [dnl
+OFPST_FLOW reply (OF1.2) (xid=0x52334509):
+ cookie=0x0, duration=0s, table=0, n_packets=0, n_bytes=0, priority=255,sctp actions=set_field:4445->sctp_dst
+], [dnl
+])
+AT_CLEANUP
+
 AT_SETUP([OFPT_PORT_MOD - OF1.0])
 AT_KEYWORDS([ofp-print])
 AT_CHECK([ovs-ofctl ofp-print "\
diff --git a/tests/ofproto-dpif.at b/tests/ofproto-dpif.at
index 32e282d..af19672 100644
--- a/tests/ofproto-dpif.at
+++ b/tests/ofproto-dpif.at
@@ -646,16 +646,54 @@ udp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_ds
 ])
 
 AT_CHECK([ovs-appctl time/warp 5000], [0], [ignore])
+
+dnl Checksum SCTP.
+AT_CHECK([ovs-ofctl monitor br0 65534 --detach --no-chdir --pidfile 2> ofctl_monitor.log])
+
+for i in 1 ; do
+    ovs-appctl netdev-dummy/receive p1 '50 54 00 00 00 07 20 22 22 22 22 22 08 00 45 00 00 24 00 00 00 00 00 84 00 00 C0 A8 00 01 C0 A8 00 02 04 58 08 af 00 00 00 00 d9 d7 91 57 01 00 00 34 cf 28 ec 4e 00 01 40 00 00 0a ff ff b7 53 24 19 00 05 00 08 7f 00 00 01 00 05 00 08 c0 a8 02 07 00 0c 00 06 00 05 00 00 80 00 00 04 c0 00 00 04'
+done
+
+OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
+AT_CHECK([cat ofctl_monitor.log], [0], [dnl
+NXT_PACKET_IN (xid=0x0): cookie=0x1 total_len=98 in_port=1 (via action) data_len=98 (unbuffered)
+sctp,metadata=0,in_port=0,vlan_tci=0x0000,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=1 cookie=0x3 total_len=102 in_port=1 reg0=0x1 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=20:22:22:22:22:22,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=2 cookie=0x4 total_len=102 in_port=1 reg0=0x1 reg1=0x2 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=3 cookie=0x5 total_len=102 in_port=1 reg0=0x1 reg1=0x2 reg2=0x3 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=4 cookie=0x6 total_len=102 in_port=1 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=192.168.0.2,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=5 cookie=0x7 total_len=102 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=1112,tp_dst=2223 sctp_csum:d9d79157
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=6 cookie=0x8 total_len=102 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=2223 sctp_csum:7f12662e
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=102 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 sctp_csum:a7e86f67
+dnl
+NXT_PACKET_IN (xid=0x0): table_id=7 cookie=0x9 total_len=102 in_port=1 tun_id=0x6 reg0=0x1 reg1=0x2 reg2=0x3 reg3=0x4 reg4=0x5 (via action) data_len=102 (unbuffered)
+sctp,metadata=0,in_port=0,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=83.83.83.83,nw_dst=84.84.84.84,nw_tos=0,nw_ecn=0,nw_ttl=0,tp_src=85,tp_dst=86 sctp_csum:a7e86f67
+])
+
 AT_CHECK([ovs-ofctl dump-flows br0 | ofctl_strip | sort], [0], [dnl
- cookie=0x1, n_packets=2, n_bytes=120, dl_src=20:22:22:22:22:22 actions=CONTROLLER:65535,resubmit(80,1)
+ cookie=0x1, n_packets=3, n_bytes=218, dl_src=20:22:22:22:22:22 actions=CONTROLLER:65535,resubmit(80,1)
  cookie=0x2, n_packets=3, n_bytes=180, dl_src=30:33:33:33:33:33 actions=mod_vlan_vid:15,CONTROLLER:65535
- cookie=0x3, table=1, n_packets=2, n_bytes=120, in_port=80 actions=load:0x1->NXM_NX_REG0[[]],mod_vlan_vid:80,CONTROLLER:65535,resubmit(81,2)
- cookie=0x4, table=2, n_packets=2, n_bytes=120, in_port=81 actions=load:0x2->NXM_NX_REG1[[]],mod_dl_src:80:81:81:81:81:81,CONTROLLER:65535,resubmit(82,3)
- cookie=0x5, table=3, n_packets=2, n_bytes=120, in_port=82 actions=load:0x3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,CONTROLLER:65535,resubmit(83,4)
- cookie=0x6, table=4, n_packets=2, n_bytes=120, in_port=83 actions=load:0x4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,CONTROLLER:65535,resubmit(84,5)
- cookie=0x7, table=5, n_packets=2, n_bytes=120, in_port=84 actions=load:0x5->NXM_NX_REG4[[]],load:0x6->NXM_NX_TUN_ID[[]],mod_nw_dst:84.84.84.84,CONTROLLER:65535,resubmit(85,6)
- cookie=0x8, table=6, n_packets=2, n_bytes=120, in_port=85 actions=mod_tp_src:85,CONTROLLER:65535,resubmit(86,7)
- cookie=0x9, table=7, n_packets=2, n_bytes=120, in_port=86 actions=mod_tp_dst:86,CONTROLLER:65535,CONTROLLER:65535
+ cookie=0x3, table=1, n_packets=3, n_bytes=218, in_port=80 actions=load:0x1->NXM_NX_REG0[[]],mod_vlan_vid:80,CONTROLLER:65535,resubmit(81,2)
+ cookie=0x4, table=2, n_packets=3, n_bytes=218, in_port=81 actions=load:0x2->NXM_NX_REG1[[]],mod_dl_src:80:81:81:81:81:81,CONTROLLER:65535,resubmit(82,3)
+ cookie=0x5, table=3, n_packets=3, n_bytes=218, in_port=82 actions=load:0x3->NXM_NX_REG2[[]],mod_dl_dst:82:82:82:82:82:82,CONTROLLER:65535,resubmit(83,4)
+ cookie=0x6, table=4, n_packets=3, n_bytes=218, in_port=83 actions=load:0x4->NXM_NX_REG3[[]],mod_nw_src:83.83.83.83,CONTROLLER:65535,resubmit(84,5)
+ cookie=0x7, table=5, n_packets=3, n_bytes=218, in_port=84 actions=load:0x5->NXM_NX_REG4[[]],load:0x6->NXM_NX_TUN_ID[[]],mod_nw_dst:84.84.84.84,CONTROLLER:65535,resubmit(85,6)
+ cookie=0x8, table=6, n_packets=3, n_bytes=218, in_port=85 actions=mod_tp_src:85,CONTROLLER:65535,resubmit(86,7)
+ cookie=0x9, table=7, n_packets=3, n_bytes=218, in_port=86 actions=mod_tp_dst:86,CONTROLLER:65535,CONTROLLER:65535
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:41 actions=mod_vlan_vid:99,mod_vlan_pcp:1,CONTROLLER:65535
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:42 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
  cookie=0xa, n_packets=3, n_bytes=180, dl_src=40:44:44:44:44:43 actions=push_mpls:0x8847,load:0xa->OXM_OF_MPLS_LABEL[[]],load:0x3->OXM_OF_MPLS_TC[[]],CONTROLLER:65535
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 996ea06..a0148a6 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -113,6 +113,8 @@ udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
 cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 ip,actions=set_field:10.4.3.77->ip_src
+sctp actions=set_field:3334->sctp_src
+sctp actions=set_field:4445->sctp_dst
 in_port=0 actions=resubmit:0
 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -130,6 +132,8 @@ OFPT_FLOW_MOD: ADD udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
 OFPT_FLOW_MOD: ADD priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535
 OFPT_FLOW_MOD: ADD actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD: ADD ip actions=load:0xa04034d->NXM_OF_IP_SRC[]
+OFPT_FLOW_MOD: ADD sctp actions=load:0xd06->OXM_OF_SCTP_SRC[]
+OFPT_FLOW_MOD: ADD sctp actions=load:0x115d->OXM_OF_SCTP_DST[]
 OFPT_FLOW_MOD: ADD in_port=0 actions=resubmit:0
 OFPT_FLOW_MOD: ADD actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -146,6 +150,8 @@ udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
 cookie=0x123456789abcdef hard_timeout=10 priority=60000 actions=controller
 actions=note:41.42.43,note:00.01.02.03.04.05.06.07,note
 ipv6,actions=set_field:fe80:0123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
+sctp actions=set_field:3334->sctp_src
+sctp actions=set_field:4445->sctp_dst
 in_port=0 actions=resubmit:0
 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -163,6 +169,8 @@ OFPT_FLOW_MOD (OF1.2): ADD table:255 udp,nw_src=192.168.0.3,tp_dst=53 actions=po
 OFPT_FLOW_MOD (OF1.2): ADD table:255 priority=60000 cookie:0x123456789abcdef hard:10 actions=CONTROLLER:65535
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=note:41.42.43.00.00.00,note:00.01.02.03.04.05.06.07.00.00.00.00.00.00,note:00.00.00.00.00.00
 OFPT_FLOW_MOD (OF1.2): ADD table:255 ipv6 actions=set_field:fe80:123:4567:890a:a6ba:dbff:fefe:59fa->ipv6_src
+OFPT_FLOW_MOD (OF1.2): ADD table:255 sctp actions=set_field:3334->sctp_src
+OFPT_FLOW_MOD (OF1.2): ADD table:255 sctp actions=set_field:4445->sctp_dst
 OFPT_FLOW_MOD (OF1.2): ADD table:255 in_port=0 actions=resubmit:0
 OFPT_FLOW_MOD (OF1.2): ADD table:255 actions=sample(probability=12345,collector_set_id=23456,obs_domain_id=34567,obs_point_id=45678)
 ]])
@@ -340,12 +348,14 @@ ipv6,ipv6_label=0x12345 actions=2
 ipv6,ipv6_src=2001:db8:3c4d:1:2:3:4:5 actions=3
 ipv6,ipv6_src=2001:db8:3c4d:1:2:3:4:5/64 actions=4
 ipv6,ipv6_dst=2001:db8:3c4d:1:2:3:4:5/127 actions=5
-tcp6,ipv6_src=2001:db8:3c4d:1::1,tp_dst=80 actions=drop 
-udp6,ipv6_src=2001:db8:3c4d:1::3,tp_dst=53 actions=drop 
+tcp6,ipv6_src=2001:db8:3c4d:1::1,tp_dst=80 actions=drop
+udp6,ipv6_src=2001:db8:3c4d:1::3,tp_dst=53 actions=drop
+sctp6,ipv6_src=2001:db8:3c4d:1::5,tp_dst=309 actions=drop
 in_port=3 icmp6,ipv6_src=2001:db8:3c4d:1::1,icmp_type=134 actions=drop
 udp dl_vlan_pcp=7 idle_timeout=5 actions=strip_vlan output:0
 tcp,nw_src=192.168.0.3,tp_dst=80 actions=set_queue:37,output:1
 udp,nw_src=192.168.0.3,tp_dst=53 actions=pop_queue,output:1
+sctp,nw_src=192.168.0.3,tp_dst=309 actions=pop_queue,output:1
 icmp6,icmp_type=135,nd_target=FEC0::1234:F045:8FFF:1111:FE4E:0571 actions=drop
 icmp6,icmp_type=135,nd_sll=00:0A:E4:25:6B:B0 actions=drop
 icmp6,icmp_type=136,nd_target=FEC0::1234:F045:8FFF:1111:FE4E:0571,nd_tll=00:0A:E4:25:6B:B1 actions=drop
@@ -372,10 +382,12 @@ NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC_W(20010db83c4d000100000
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_DST_W(20010db83c4d00010002000300040004/fffffffffffffffffffffffffffffffe) actions=output:5
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010000000000000001), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(0050) actions=drop
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010000000000000003), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST(0035) actions=drop
+NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010000000000000005), NXM_OF_IP_PROTO(84), OXM_OF_SCTP_DST(0135) actions=drop
 NXT_FLOW_MOD: ADD NXM_OF_IN_PORT(0003), NXM_OF_ETH_TYPE(86dd), NXM_NX_IPV6_SRC(20010db83c4d00010000000000000001), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(86) actions=drop
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800), NXM_OF_VLAN_TCI_W(f000/f000), NXM_OF_IP_PROTO(11) idle:5 actions=strip_vlan,output:0
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(c0a80003), NXM_OF_IP_PROTO(06), NXM_OF_TCP_DST(0050) actions=set_queue:37,output:1
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(c0a80003), NXM_OF_IP_PROTO(11), NXM_OF_UDP_DST(0035) actions=pop_queue,output:1
+NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(0800), NXM_OF_IP_SRC(c0a80003), NXM_OF_IP_PROTO(84), OXM_OF_SCTP_DST(0135) actions=pop_queue,output:1
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_TARGET(fec000001234f0458fff1111fe4e0571) actions=drop
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(87), NXM_NX_ND_SLL(000ae4256bb0) actions=drop
 NXT_FLOW_MOD: ADD NXM_OF_ETH_TYPE(86dd), NXM_OF_IP_PROTO(3a), NXM_NX_ICMPV6_TYPE(88), NXM_NX_ND_TARGET(fec000001234f0458fff1111fe4e0571), NXM_NX_ND_TLL(000ae4256bb1) actions=drop
@@ -1145,6 +1157,14 @@ xxxxxxxx xxxxxxxx 01bb xxxx
 0038204f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 11 xxxx dnl
 xxxxxxxx xxxxxxxx xxxx 01bb
 
+# sctp,tp_src=443
+0038208f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 84 xxxx dnl
+xxxxxxxx xxxxxxxx 01bb xxxx
+
+# sctp,tp_dst=443
+0038204f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 84 xxxx dnl
+xxxxxxxx xxxxxxxx xxxx 01bb
+
 # icmp,icmp_type=5
 0038208f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 01 xxxx dnl
 xxxxxxxx xxxxxxxx 0005 xxxx
@@ -1153,7 +1173,7 @@ xxxxxxxx xxxxxxxx 0005 xxxx
 0038204f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 01 xxxx dnl
 xxxxxxxx xxxxxxxx xxxx 0008
 
-dnl Ignore tp_src if not TCP or UDP:
+dnl Ignore tp_src if not TCP/UDP/SCTP:
 # ip,nw_proto=21,tp_src=443
 # normal:  3: 8f -> cf
 # normal: 36: 01 -> 00
@@ -1164,7 +1184,7 @@ dnl Ignore tp_src if not TCP or UDP:
 0038208f xxxx xxxxxxxxxxxx xxxxxxxxxxxx xxxx xx xx 0800 xx 15 xxxx dnl
 xxxxxxxx xxxxxxxx 01bb xxxx
 
-dnl Ignore tp_dst if not TCP or UDP:
+dnl Ignore tp_dst if not TCP/UDP/SCTP:
 # ip,nw_proto=21,tp_dst=443
 # normal:  3: 4f -> cf
 # normal: 38: 01 -> 00
@@ -1408,28 +1428,25 @@ dnl Try invalid TOS:
 0000 00 00 0800 00 11 00000000ffffffff 00000000ffffffff 0000 01bb dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl SCTP, no ports.
-# ip,nw_proto=132
+# sctp
 0000 0058 00000000 000003d7 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 84 00000000ffffffff 00000000ffffffff 0000 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl SCTP tp_src matching not supported:
-# bad ofp11_match: OFPBMC_BAD_FIELD
+# sctp,tp_src=443
 0000 0058 00000000 00000397 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 84 00000000ffffffff 00000000ffffffff 01bb 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl SCTP tp_dst matching not supported:
-# bad ofp11_match: OFPBMC_BAD_FIELD
+# sctp,tp_dst=443
 0000 0058 00000000 00000357 dnl
 000000000000ffffffffffff 000000000000ffffffffffff dnl
 0000 00 00 0800 00 84 00000000ffffffff 00000000ffffffff 0000 01bb dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl Ignore tp_src if not TCP or UDP or SCTP:
+dnl Ignore tp_src if not TCP/UDP/SCTP:
 # ip,nw_proto=21
 # 11: 97 -> d7
 # 60: 01 -> 00
@@ -1439,7 +1456,7 @@ dnl Ignore tp_src if not TCP or UDP or SCTP:
 0000 00 00 0800 00 15 00000000ffffffff 00000000ffffffff 01bb 0000 dnl
 00000000 00 000000 0000000000000000ffffffffffffffff
 
-dnl Ignore tp_dst if not TCP or UDP or SCTP:
+dnl Ignore tp_dst if not TCP/UDP/SCTP:
 # ip,nw_proto=22
 # 11: 57 -> d7
 # 62: 01 -> 00
@@ -1640,6 +1657,20 @@ OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(11) OXM_OF_UDP_DST_W(5005/FFFF)
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(11) OXM_OF_UDP_DST_W(5005/0000)
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(02) OXM_OF_UDP_DST(1293)
 
+# SCTP source port
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_SRC(8732)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_SRC_W(0132/01FF)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_SRC_W(0132/FFFF)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_SRC_W(0132/0000)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(06) OXM_OF_SCTP_SRC(7823)
+
+# SCTP destination port
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_DST(1782)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_DST_W(5005/F00F)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_DST_W(5005/FFFF)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(84) OXM_OF_SCTP_DST_W(5005/0000)
+OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(02) OXM_OF_SCTP_DST(1293)
+
 # ICMP type
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(01) OXM_OF_ICMPV4_TYPE(12)
 OXM_OF_ETH_TYPE(0800) OXM_OF_IP_PROTO(00) OXM_OF_ICMPV4_TYPE(10)
@@ -1842,6 +1873,20 @@ OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(11), OXM_OF_UDP_DST(5005)
 OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(11)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
 
+# SCTP source port
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_SRC(8732)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_SRC_W(0132/01ff)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_SRC(0132)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
+# SCTP destination port
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_DST(1782)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_DST_W(5005/f00f)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84), OXM_OF_SCTP_DST(5005)
+OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(84)
+nx_pull_match() returned error OFPBMC_BAD_PREREQ
+
 # ICMP type
 OXM_OF_ETH_TYPE(0800), OXM_OF_IP_PROTO(01), OXM_OF_ICMPV4_TYPE(12)
 nx_pull_match() returned error OFPBMC_BAD_PREREQ
diff --git a/tests/test-netflow.c b/tests/test-netflow.c
index 413837e..e995852 100644
--- a/tests/test-netflow.c
+++ b/tests/test-netflow.c
@@ -100,6 +100,11 @@ print_netflow(struct ofpbuf *buf)
                    ntohs(rec->src_port), ntohs(rec->dst_port));
             break;
 
+        case IPPROTO_SCTP:
+            printf(", SCTP %"PRIu16" > %"PRIu16,
+                   ntohs(rec->src_port), ntohs(rec->dst_port));
+            break;
+
         case IPPROTO_ICMP:
             printf(", ICMP %"PRIu16":%"PRIu16,
                    ntohs(rec->dst_port) >> 8,
@@ -120,6 +125,7 @@ print_netflow(struct ofpbuf *buf)
 
         if (rec->ip_proto != IPPROTO_TCP &&
             rec->ip_proto != IPPROTO_UDP &&
+            rec->ip_proto != IPPROTO_SCTP &&
             rec->ip_proto != IPPROTO_ICMP) {
             if (rec->src_port != htons(0)) {
                 printf(", src_port %"PRIu16, ntohs(rec->src_port));
diff --git a/utilities/ovs-ofctl.8.in b/utilities/ovs-ofctl.8.in
index 47b591a..85b2e44 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -537,8 +537,8 @@ above).
 .
 .IP \fBtp_src=\fIport\fR
 .IQ \fBtp_dst=\fIport\fR
-When \fBdl_type\fR and \fBnw_proto\fR specify TCP or UDP, \fBtp_src\fR
-and \fBtp_dst\fR match the UDP or TCP source or destination port
+When \fBdl_type\fR and \fBnw_proto\fR specify TCP or UDP or SCTP, \fBtp_src\fR
+and \fBtp_dst\fR match the UDP or TCP or SCTP source or destination port
 \fIport\fR, respectively, which is specified as a decimal number
 between 0 and 65535, inclusive (e.g. 80 to match packets originating
 from a HTTP server).
@@ -548,7 +548,7 @@ these settings are ignored (see \fBFlow Syntax\fR above).
 .
 .IP \fBtp_src=\fIport\fB/\fImask\fR
 .IQ \fBtp_dst=\fIport\fB/\fImask\fR
-Bitwise match on TCP (or UDP) source or destination port,
+Bitwise match on TCP (or UDP or SCTP) source or destination port,
 respectively.  The \fIport\fR and \fImask\fR are 16-bit numbers
 written in decimal or in hexadecimal prefixed by \fB0x\fR.  Each 1-bit
 in \fImask\fR requires that the corresponding bit in \fIport\fR must
@@ -606,7 +606,7 @@ ports.
 .IP
 Like the exact-match forms of \fBtp_src\fR and \fBtp_dst\fR described
 above, the bitwise match forms apply only when \fBdl_type\fR and
-\fBnw_proto\fR specify TCP or UDP.
+\fBnw_proto\fR specify TCP or UDP or SCTP.
 .
 .IP \fBicmp_type=\fItype\fR
 .IQ \fBicmp_code=\fIcode\fR
@@ -659,6 +659,9 @@ Same as \fBdl_type=0x0800,nw_proto=6\fR.
 .IP \fBudp\fR
 Same as \fBdl_type=0x0800,nw_proto=17\fR.
 .
+.IP \fBsctp\fR
+Same as \fBdl_type=0x0800,nw_proto=132\fR.
+.
 .IP \fBarp\fR
 Same as \fBdl_type=0x0806\fR.
 .
@@ -827,6 +830,9 @@ Same as \fBdl_type=0x86dd,nw_proto=6\fR.
 .IP \fBudp6\fR
 Same as \fBdl_type=0x86dd,nw_proto=17\fR.
 .
+.IP \fBsctp6\fR
+Same as \fBdl_type=0x86dd,nw_proto=132\fR.
+.
 .IP \fBicmp6\fR
 Same as \fBdl_type=0x86dd,nw_proto=58\fR.
 .
@@ -983,10 +989,10 @@ Sets the IPv4 source address to \fIip\fR.
 Sets the IPv4 destination address to \fIip\fR.
 .
 .IP \fBmod_tp_src\fB:\fIport\fR
-Sets the TCP or UDP source port to \fIport\fR.
+Sets the TCP or UDP or SCTP source port to \fIport\fR.
 .
 .IP \fBmod_tp_dst\fB:\fIport\fR
-Sets the TCP or UDP destination port to \fIport\fR.
+Sets the TCP or UDP or SCTP destination port to \fIport\fR.
 .
 .IP \fBmod_nw_tos\fB:\fItos\fR
 Sets the IPv4 ToS/DSCP field to \fItos\fR, which must be a multiple of
@@ -1545,7 +1551,7 @@ A flow that does not specify any part of a field that is used for sorting is
 sorted after all the flows that do specify the field.  For example,
 \fB\-\-sort=tcp_src\fR will sort all the flows that specify a TCP
 source port in ascending order, followed by the flows that do not
-specify a TCP source port at all.  
+specify a TCP source port at all.
 .IP \(bu
 A flow that only specifies some bits in a field is sorted as if the
 wildcarded bits were zero.  For example, \fB\-\-sort=nw_src\fR would
-- 
1.7.2.5




More information about the dev mailing list