Signed-off-by: Joe Stringer <j...@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 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev