[ovs-dev] [PATCH 4/4] ofp-util: Support matching on SCTP src, dst ports

Joe Stringer joe at wand.net.nz
Fri Aug 31 10:44:35 UTC 2012


Signed-off-by: Joe Stringer <joe at wand.net.nz>
---
 lib/classifier.c         |    4 ++++
 lib/meta-flow.c          |   40 ++++++++++++++++++++++++++++++++++++++++
 lib/meta-flow.h          |    4 ++++
 lib/nx-match.c           |    3 +++
 lib/ofp-parse.c          |    2 ++
 lib/ofp-print.c          |    6 ++++++
 lib/ofp-util.c           |    8 +++-----
 tests/ovs-ofctl.at       |    9 +++------
 tests/test-netflow.c     |    6 ++++++
 utilities/ovs-ofctl.8.in |    6 ++++++
 10 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/lib/classifier.c b/lib/classifier.c
index 38f1a4f..9e1b322 100644
--- a/lib/classifier.c
+++ b/lib/classifier.c
@@ -624,6 +624,8 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
                     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;
@@ -640,6 +642,8 @@ cls_rule_format(const struct cls_rule *rule, struct ds *s)
                     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 3713ca4..7fa3881 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -387,6 +387,26 @@ static const struct mf_field mf_fields[MFF_N_IDS] = {
     },
 
     {
+        MFF_SCTP_SRC, "sctp_src", NULL,
+        MF_FIELD_SIZES(be16),
+        MFM_FULLY, 0,
+        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, 0,
+        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, 0,
@@ -640,11 +660,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->tp_src_mask;
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
         return !wc->tp_dst_mask;
@@ -752,10 +774,12 @@ mf_get_mask(const struct mf_field *mf, const struct flow_wildcards *wc,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         mask->be16 = wc->tp_src_mask;
         break;
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         mask->be16 = wc->tp_dst_mask;
         break;
 
@@ -835,6 +859,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:
@@ -894,6 +920,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:
@@ -1045,11 +1073,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;
 
@@ -1188,11 +1218,13 @@ mf_set_value(const struct mf_field *mf,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         cls_rule_set_tp_src(rule, value->be16);
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         cls_rule_set_tp_dst(rule, value->be16);
         break;
 
@@ -1333,11 +1365,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;
 
@@ -1495,6 +1529,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
     case MFF_ICMPV4_TYPE:
     case MFF_ICMPV6_TYPE:
         rule->wc.tp_src_mask = htons(0);
@@ -1503,6 +1538,7 @@ mf_set_wild(const struct mf_field *mf, struct cls_rule *rule)
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
     case MFF_ICMPV4_CODE:
     case MFF_ICMPV6_CODE:
         rule->wc.tp_dst_mask = htons(0);
@@ -1641,11 +1677,13 @@ mf_set(const struct mf_field *mf,
 
     case MFF_TCP_SRC:
     case MFF_UDP_SRC:
+    case MFF_SCTP_SRC:
         cls_rule_set_tp_src_masked(rule, value->be16, mask->be16);
         break;
 
     case MFF_TCP_DST:
     case MFF_UDP_DST:
+    case MFF_SCTP_DST:
         cls_rule_set_tp_dst_masked(rule, value->be16, mask->be16);
         break;
 
@@ -1743,6 +1781,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 12a4baa..91c1d31 100644
--- a/lib/meta-flow.h
+++ b/lib/meta-flow.h
@@ -98,6 +98,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 */
 
@@ -164,6 +167,7 @@ enum mf_prereqs {
     /* L2+L3 requirements. */
     MFP_TCP,                    /* On IPv4 or IPv6. */
     MFP_UDP,                    /* On IPv4 or IPv6. */
+    MFP_SCTP,
     MFP_ICMPV4,
     MFP_ICMPV6,
 
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 16c1674..82cd7ef 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -527,6 +527,9 @@ nxm_put_ip(struct ofpbuf *b, const struct cls_rule *cr,
                         flow->tp_src, cr->wc.tp_src_mask);
             nxm_put_16m(b, oxm ? OXM_OF_UDP_DST : NXM_OF_UDP_DST,
                         flow->tp_dst, cr->wc.tp_dst_mask);
+        } else if (flow->nw_proto == IPPROTO_SCTP) {
+            nxm_put_16m(b, OXM_OF_SCTP_SRC, flow->tp_src, cr->wc.tp_src_mask);
+            nxm_put_16m(b, OXM_OF_SCTP_DST, flow->tp_dst, cr->wc.tp_dst_mask);
         } else if (flow->nw_proto == icmp_proto) {
             if (cr->wc.tp_src_mask) {
                 nxm_put_8(b, icmp_type, ntohs(flow->tp_src));
diff --git a/lib/ofp-parse.c b/lib/ofp-parse.c
index 0d904b1..e4d7a93 100644
--- a/lib/ofp-parse.c
+++ b/lib/ofp-parse.c
@@ -522,11 +522,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 },
     };
     const struct protocol *p;
 
diff --git a/lib/ofp-print.c b/lib/ofp-print.c
index 99e6456..221baa4 100644
--- a/lib/ofp-print.c
+++ b/lib/ofp-print.c
@@ -75,6 +75,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,
+                          ntohs(sh->sctp_csum));
         }
     }
 
@@ -607,6 +611,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 ce9bb74..2259f0d 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -427,6 +427,7 @@ ofputil_cls_rule_from_ofp11_match(const struct ofp11_match *match,
 
         case IPPROTO_TCP:
         case IPPROTO_UDP:
+        case IPPROTO_SCTP:
             if (!(wc & (OFPFW11_TP_SRC))) {
                 cls_rule_set_tp_src(rule, match->tp_src);
             }
@@ -435,11 +436,6 @@ ofputil_cls_rule_from_ofp11_match(const struct ofp11_match *match,
             }
             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;
@@ -3608,12 +3604,14 @@ ofputil_normalize_rule__(struct cls_rule *rule, bool may_log)
         may_match = MAY_NW_PROTO | MAY_IPVx | MAY_NW_ADDR;
         if (rule->flow.nw_proto == IPPROTO_TCP ||
             rule->flow.nw_proto == IPPROTO_UDP ||
+            rule->flow.nw_proto == IPPROTO_SCTP ||
             rule->flow.nw_proto == IPPROTO_ICMP) {
             may_match |= MAY_TP_ADDR;
         }
     } else if (rule->flow.dl_type == htons(ETH_TYPE_IPV6)) {
         may_match = MAY_NW_PROTO | MAY_IPVx | MAY_IPV6;
         if (rule->flow.nw_proto == IPPROTO_TCP ||
+            rule->flow.nw_proto == IPPROTO_SCTP ||
             rule->flow.nw_proto == IPPROTO_UDP) {
             may_match |= MAY_TP_ADDR;
         } else if (rule->flow.nw_proto == IPPROTO_ICMPV6) {
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
index 947f985..af2cb53 100644
--- a/tests/ovs-ofctl.at
+++ b/tests/ovs-ofctl.at
@@ -1159,22 +1159,19 @@ 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
diff --git a/tests/test-netflow.c b/tests/test-netflow.c
index 85ab5e7..0cf44eb 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 aad9325..29386da 100644
--- a/utilities/ovs-ofctl.8.in
+++ b/utilities/ovs-ofctl.8.in
@@ -637,6 +637,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.
 .
@@ -784,6 +787,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.
 .
-- 
1.7.2.5




More information about the dev mailing list