[ovs-dev] [PATCH ovn v3 2/2] Add sctp_abort logical flow action.

Mark Michelson mmichels at redhat.com
Wed Jan 13 20:15:53 UTC 2021


On 1/13/21 10:05 AM, Numan Siddique wrote:
> 
> 
> On Wed, Jan 13, 2021 at 2:19 AM Mark Michelson <mmichels at redhat.com 
> <mailto:mmichels at redhat.com>> wrote:
> 
>     This is used in similar situations as tcp_reset, only for SCTP flows.
> 
>     The "router port unreachable" test has been expanded to test SCTP. In
>     doing so, two test cases were removed because they specified SCTP as the
>     protocol and expected ICMP replies.
> 
>     Signed-off-by: Mark Michelson <mmichels at redhat.com
>     <mailto:mmichels at redhat.com>>
> 
> 
> Acked-by: Numan Siddique <numans at ovn.org <mailto:numans at ovn.org>>
> 
> Thanks
> Numan

Thanks Numan,

I merged both patches to master.

> 
>     ---
>       controller/pinctrl.c    |  5 +++
>       include/ovn/actions.h   |  7 ++++
>       lib/actions.c           | 22 +++++++++++
>       northd/ovn-northd.8.xml |  5 ++-
>       northd/ovn-northd.c     | 28 +++++++++++++-
>       tests/ovn.at <http://ovn.at>            | 84
>     ++++++++++++++++++++++++++++++++++++++++-
>       utilities/ovn-trace.c   |  5 +++
>       7 files changed, 150 insertions(+), 6 deletions(-)
> 
>     diff --git a/controller/pinctrl.c b/controller/pinctrl.c
>     index ce11aa365..b9880e257 100644
>     --- a/controller/pinctrl.c
>     +++ b/controller/pinctrl.c
>     @@ -3057,6 +3057,11 @@ process_packet_in(struct rconn *swconn, const
>     struct ofp_header *msg)
>                                        &userdata, false);
>               break;
> 
>     +    case ACTION_OPCODE_SCTP_ABORT:
>     +        pinctrl_handle_sctp_abort(swconn, &headers, &packet,
>     +                                  &pin.flow_metadata, &userdata,
>     false);
>     +        break;
>     +
>           case ACTION_OPCODE_REJECT:
>               pinctrl_handle_reject(swconn, &headers, &packet,
>     &pin.flow_metadata,
>                                     &userdata);
>     diff --git a/include/ovn/actions.h b/include/ovn/actions.h
>     index d104d4d64..be87e6135 100644
>     --- a/include/ovn/actions.h
>     +++ b/include/ovn/actions.h
>     @@ -106,6 +106,7 @@ struct ovn_extend_table;
>           OVNACT(CHK_LB_HAIRPIN_REPLY, ovnact_result)       \
>           OVNACT(CT_SNAT_TO_VIP,    ovnact_null)            \
>           OVNACT(BFD_MSG,           ovnact_null)            \
>     +    OVNACT(SCTP_ABORT,        ovnact_nest)            \
> 
>       /* enum ovnact_type, with a member OVNACT_<ENUM> for each action. */
>       enum OVS_PACKED_ENUM ovnact_type {
>     @@ -634,6 +635,12 @@ enum action_opcode {
>            *  The actions, in OpenFlow 1.3 format, follow the action_header.
>            */
>           ACTION_OPCODE_BFD_MSG,
>     +
>     +    /* "sctp_abort { ...actions... }".
>     +     *
>     +     * The actions, in OpenFlow 1.3 format, follow the action_header.
>     +     */
>     +    ACTION_OPCODE_SCTP_ABORT,
>       };
> 
>       /* Header. */
>     diff --git a/lib/actions.c b/lib/actions.c
>     index 86be97f44..56b8fab62 100644
>     --- a/lib/actions.c
>     +++ b/lib/actions.c
>     @@ -1490,6 +1490,12 @@ parse_TCP_RESET(struct action_context *ctx)
>           parse_nested_action(ctx, OVNACT_TCP_RESET, "tcp", ctx->scope);
>       }
> 
>     +static void
>     +parse_SCTP_ABORT(struct action_context *ctx)
>     +{
>     +    parse_nested_action(ctx, OVNACT_SCTP_ABORT, "sctp", ctx->scope);
>     +}
>     +
>       static void
>       parse_ND_NA(struct action_context *ctx)
>       {
>     @@ -1571,6 +1577,12 @@ format_TCP_RESET(const struct ovnact_nest
>     *nest, struct ds *s)
>           format_nested_action(nest, "tcp_reset", s);
>       }
> 
>     +static void
>     +format_SCTP_ABORT(const struct ovnact_nest *nest, struct ds *s)
>     +{
>     +    format_nested_action(nest, "sctp_abort", s);
>     +}
>     +
>       static void
>       format_ND_NA(const struct ovnact_nest *nest, struct ds *s)
>       {
>     @@ -1700,6 +1712,14 @@ encode_TCP_RESET(const struct ovnact_nest *on,
>           encode_nested_actions(on, ep, ACTION_OPCODE_TCP_RESET, ofpacts);
>       }
> 
>     +static void
>     +encode_SCTP_ABORT(const struct ovnact_nest *on,
>     +                  const struct ovnact_encode_params *ep,
>     +                  struct ofpbuf *ofpacts)
>     +{
>     +    encode_nested_actions(on, ep, ACTION_OPCODE_SCTP_ABORT, ofpacts);
>     +}
>     +
>       static void
>       encode_REJECT(const struct ovnact_nest *on,
>                     const struct ovnact_encode_params *ep,
>     @@ -3837,6 +3857,8 @@ parse_action(struct action_context *ctx)
>               ovnact_put_IGMP(ctx->ovnacts);
>           } else if (lexer_match_id(ctx->lexer, "tcp_reset")) {
>               parse_TCP_RESET(ctx);
>     +    } else if (lexer_match_id(ctx->lexer, "sctp_abort")) {
>     +        parse_SCTP_ABORT(ctx);
>           } else if (lexer_match_id(ctx->lexer, "nd_na")) {
>               parse_ND_NA(ctx);
>           } else if (lexer_match_id(ctx->lexer, "nd_na_router")) {
>     diff --git a/northd/ovn-northd.8.xml b/northd/ovn-northd.8.xml
>     index 398a3452e..70065a36d 100644
>     --- a/northd/ovn-northd.8.xml
>     +++ b/northd/ovn-northd.8.xml
>     @@ -518,8 +518,9 @@
>               flows with the
>               <code>tcp_reset { output <-> inport;
>               next(pipeline=egress,table=5);}</code>
>     -        action for TCP connections and <code>icmp4/icmp6</code> action
>     -        for UDP connections.
>     +        action for TCP connections,<code>icmp4/icmp6</code> action
>     +        for UDP connections, and <code>sctp_abort {output <-%gt;
>     inport;
>     +        next(pipeline=egress,table=5);}</code> action for SCTP
>     associations.
>             </li>
>             <li>
>               Other ACLs translate to <code>drop;</code> for new or
>     untracked
>     diff --git a/northd/ovn-northd.c b/northd/ovn-northd.c
>     index 50507685b..332dbc112 100644
>     --- a/northd/ovn-northd.c
>     +++ b/northd/ovn-northd.c
>     @@ -10529,7 +10529,7 @@ build_ipv6_input_flows_for_lrouter_port(
>                                         &op->nbrp->header_, lflows);
>               }
> 
>     -        /* UDP/TCP port unreachable */
>     +        /* UDP/TCP/SCTP port unreachable */
>               if (!smap_get(&op->od->nbr->options, "chassis")
>                   && !op->od->l3dgw_port) {
>                   for (int i = 0; i < op->lrp_networks.n_ipv6_addrs; i++) {
>     @@ -10545,6 +10545,18 @@ build_ipv6_input_flows_for_lrouter_port(
>                                               80, ds_cstr(match), action,
>                                               &op->nbrp->header_);
> 
>     +                ds_clear(match);
>     +                ds_put_format(match,
>     +                              "ip6 && ip6.dst == %s &&
>     !ip.later_frag && sctp",
>     +                              op->lrp_networks.ipv6_addrs[i].addr_s);
>     +                action = "sctp_abort {"
>     +                         "eth.dst <-> eth.src; "
>     +                         "ip6.dst <-> ip6.src; "
>     +                         "next; };";
>     +                ovn_lflow_add_with_hint(lflows, op->od,
>     S_ROUTER_IN_IP_INPUT,
>     +                                        80, ds_cstr(match), action,
>     +                                        &op->nbrp->header_);
>     +
>                       ds_clear(match);
>                       ds_put_format(match,
>                                     "ip6 && ip6.dst == %s &&
>     !ip.later_frag && udp",
>     @@ -10806,7 +10818,7 @@ build_lrouter_ipv4_ip_input(struct ovn_port *op,
> 
>               if (!smap_get(&op->od->nbr->options, "chassis")
>                   && !op->od->l3dgw_port) {
>     -            /* UDP/TCP port unreachable. */
>     +            /* UDP/TCP/SCTP port unreachable. */
>                   for (int i = 0; i < op->lrp_networks.n_ipv4_addrs; i++) {
>                       ds_clear(match);
>                       ds_put_format(match,
>     @@ -10835,6 +10847,18 @@ build_lrouter_ipv4_ip_input(struct ovn_port
>     *op,
>                                               80, ds_cstr(match), action,
>                                               &op->nbrp->header_);
> 
>     +                ds_clear(match);
>     +                ds_put_format(match,
>     +                              "ip4 && ip4.dst == %s &&
>     !ip.later_frag && sctp",
>     +                              op->lrp_networks.ipv4_addrs[i].addr_s);
>     +                action = "sctp_abort {"
>     +                         "eth.dst <-> eth.src; "
>     +                         "ip4.dst <-> ip4.src; "
>     +                         "next; };";
>     +                ovn_lflow_add_with_hint(lflows, op->od,
>     S_ROUTER_IN_IP_INPUT,
>     +                                        80, ds_cstr(match), action,
>     +                                        &op->nbrp->header_);
>     +
>                       ds_clear(match);
>                       ds_put_format(match,
>                                     "ip4 && ip4.dst == %s &&
>     !ip.later_frag",
>     diff --git a/tests/ovn.at <http://ovn.at> b/tests/ovn.at <http://ovn.at>
>     index c71e81822..f575eecb5 100644
>     --- a/tests/ovn.at <http://ovn.at>
>     +++ b/tests/ovn.at <http://ovn.at>
>     @@ -1637,6 +1637,17 @@ tcp_reset { };
>           encodes as controller(userdata=00.00.00.0b.00.00.00.00)
>           has prereqs tcp
> 
>     +# sctp_abort
>     +sctp_abort {eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>     +    formats as sctp_abort { eth.dst = ff:ff:ff:ff:ff:ff; output; };
>     output;
>     +    encodes as
>     controller(userdata=00.00.00.18.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     +    has prereqs sctp
>     +
>     +sctp_abort { };
>     +    formats as sctp_abort { drop; };
>     +    encodes as controller(userdata=00.00.00.18.00.00.00.00)
>     +    has prereqs sctp
>     +
>       # reject
>       reject { eth.dst = ff:ff:ff:ff:ff:ff; output; }; output;
>           encodes as
>     controller(userdata=00.00.00.16.00.00.00.00.00.19.00.10.80.00.06.06.ff.ff.ff.ff.ff.ff.00.00.ff.ff.00.10.00.00.23.20.00.0e.ff.f8.40.00.00.00),resubmit(,64)
>     @@ -14354,6 +14365,45 @@ test_tcp_syn_packet() {
>           as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>       }
> 
>     +# test_sctp_init_packet INPORT HV ETH_SRC ETH_DST IPV4_SRC IPV4_DST
>     IP_CHKSUM SCTP_SPORT SCTP_DPORT SCTP_INIT_TAG SCTP_CHKSUM
>     EXP_IP_CHKSUM EXP_SCTP_ABORT_CHKSUM
>     +#
>     +# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an SCTP INIT chunk with
>     +# ETH_SRC, ETH_DST, IPV4_SRC, IPV4_DST, IP_CHKSUM, SCTP_SPORT,
>     SCTP_DPORT, and SCTP_CHKSUM as specified.
>     +# The INIT "initiate_tag" will be set to SCTP_INIT_TAG.
>     +# EXP_IP_CHKSUM and EXP_SCTP_CHKSUM are the ip and sctp checksums
>     of the SCTP ABORT chunk generated by OVN logical router
>     +#
>     +# INPORT is an lport number, e.g. 1 for vif1.
>     +# HV is a hypervisor number.
>     +# ETH_SRC and ETH_DST are each 12 hex digits.
>     +# IPV4_SRC and IPV4_DST are each 8 hex digits.
>     +# SCTP_SPORT and SCTP_DPORT are 4 hex digits.
>     +# IP_CHKSUM and EXP_IP_CHKSUM are 4 hex digits.
>     +# SCTP_CHKSUM and EXP_SCTP_CHKSUM are 8 hex digits.
>     +test_sctp_init_packet() {
>     +    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv4_src=$5
>     ipv4_dst=$6 ip_chksum=$7
>     +    local sctp_sport=$8 sctp_dport=$9 sctp_init_tag=${10}
>     sctp_chksum=${11}
>     +    local exp_ip_chksum=${12} exp_sctp_abort_chksum=${13}
>     +
>     +    local ip_ttl=ff
>     +    local eth_hdr=${eth_dst}${eth_src}0800
>     +    local
>     ip_hdr=4500002500004000${ip_ttl}84${ip_chksum}${ipv4_src}${ipv4_dst}
>     +    local sctp_hdr=${sctp_sport}${sctp_dport}00000000${sctp_chksum}
>     +    local
>     sctp_init=01000014${sctp_init_tag}0000000000010001${sctp_init_tag}
>     +
>     +    local packet=${eth_hdr}${ip_hdr}${sctp_hdr}${sctp_init}
>     +
>     +    local sctp_abort_ttl=3e
>     +    local reply_eth_hdr=${eth_src}${eth_dst}0800
>     +    local
>     reply_ip_hdr=4500002400004000${sctp_abort_ttl}84${exp_ip_chksum}${ipv4_dst}${ipv4_src}
>     +    local
>     reply_sctp_hdr=${sctp_dport}${sctp_sport}${sctp_init_tag}${exp_sctp_abort_chksum}
>     +    local reply_sctp_abort=06000004
>     +
>     +    local
>     reply=${reply_eth_hdr}${reply_ip_hdr}${reply_sctp_hdr}${reply_sctp_abort}
>     +    echo $reply >> vif$inport.expected
>     +
>     +    check as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     +}
>     +
>       # test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>     TCP_SPORT TCP_DPORT TCP_CHKSUM EXP_TCP_RST_CHKSUM
>       #
>       # Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is a TCP syn segment with
>     @@ -14374,6 +14424,36 @@ test_tcp6_packet() {
>           as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>       }
> 
>     +# test_tcp6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_ROUTER
>     SCTP_SPORT SCTP_DPORT SCTP_INIT_TAG SCTP_CHKSUM EXP_SCTP_ABORT_CHKSUM
>     +#
>     +# Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an SCTP INIT chunk with
>     +# ETH_SRC, ETH_DST, IPV6_SRC, IPV6_ROUTER, SCTP_SPORT, SCTP_DPORT
>     and SCTP_CHKSUM as specified.
>     +# The INIT "initiate_tag" will be set to SCTP_INIT_TAG.
>     +# EXP_SCTP_CHKSUM is the sctp checksum of the SCTP ABORT chunk
>     generated by OVN logical router
>     +test_sctp6_packet() {
>     +    local inport=$1 hv=$2 eth_src=$3 eth_dst=$4 ipv6_src=$5
>     ipv6_router=$6
>     +    local sctp_sport=$7 sctp_dport=$8 sctp_init_tag=$9
>     sctp_chksum=${10}
>     +    local exp_sctp_abort_chksum=${11}
>     +    shift 11
>     +
>     +    local eth_hdr=${eth_dst}${eth_src}86dd
>     +    local ip_hdr=60000000002084ff${ipv6_src}${ipv6_router}
>     +    local sctp_hdr=${sctp_sport}${sctp_dport}00000000${sctp_chksum}
>     +    local
>     sctp_init=01000014${sctp_init_tag}0000000000010001${sctp_init_tag}
>     +
>     +    local packet=${eth_hdr}${ip_hdr}${sctp_hdr}${sctp_init}
>     +
>     +    local reply_eth_hdr=${eth_src}${eth_dst}86dd
>     +    local reply_ip_hdr=600000000010843e${ipv6_router}${ipv6_src}
>     +    local
>     reply_sctp_hdr=${sctp_dport}${sctp_sport}${sctp_init_tag}${exp_sctp_abort_chksum}
>     +    local reply_sctp_abort=06000004
>     +
>     +    local
>     reply=${reply_eth_hdr}${reply_ip_hdr}${reply_sctp_hdr}${reply_sctp_abort}
>     +    echo $reply >> vif$inport.expected
>     +
>     +    check as hv$hv ovs-appctl netdev-dummy/receive vif$inport $packet
>     +}
>     +
>       # test_ip6_packet INPORT HV ETH_SRC ETH_DST IPV6_SRC IPV6_DST
>     IPV6_PROTO IPV6_LEN DATA EXP_ICMP_CODE EXP_ICMP_CHKSUM
>       #
>       # Causes a packet to be received on INPORT of the hypervisor HV.
>     The packet is an IPv6
>     @@ -14428,13 +14508,13 @@ OVN_POPULATE_ARP
>       ovn-nbctl --wait=hv sync
> 
>       test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1
>     1) $(ip_to_hex 192 168 1 254) 11 0000 f87c f485 0303
>     -test_ip_packet 1 1 000000000001 00000000ff01 $(ip_to_hex 192 168 1
>     1) $(ip_to_hex 192 168 1 254) 84 0000 f87c f413 0302
>       test_ip6_packet 1 1 000000000001 00000000ff01
>     20010db8000100000000000000000011 20010db8000100000000000000000001 11
>     0015 dbb8303900155bac6b646f65206676676e6d66720a 0104 1d31
>       OVN_CHECK_PACKETS([hv1/vif1-tx.pcap], [vif1.expected])
> 
>       test_tcp_syn_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 0000 b680 6e05
>     -test_ip6_packet 2 2 000000000002 00000000ff02
>     20010db8000200000000000000000011 20010db8000200000000000000000001 84
>     0004 01020304 0103 5e74
>     +test_sctp_init_packet 2 2 000000000002 00000000ff02 $(ip_to_hex 192
>     168 2 1) $(ip_to_hex 192 168 2 254) 0000 8b40 3039 00000001 82112601
>     b606 10fe95b6
>       test_tcp6_packet 2 2 000000000002 00000000ff02
>     20010db8000200000000000000000011 20010db8000200000000000000000001
>     8b40 3039 0000 98cd
>     +test_sctp6_packet 2 2 000000000002 00000000ff02
>     20010db8000200000000000000000011 20010db8000200000000000000000001
>     8b40 3039 00000002 C0379D5A 39f23aaf
>       OVN_CHECK_PACKETS([hv2/vif2-tx.pcap], [vif2.expected])
> 
>       OVN_CLEANUP([hv1], [hv2])
>     diff --git a/utilities/ovn-trace.c b/utilities/ovn-trace.c
>     index d54ffbcd9..c0a0edc0a 100644
>     --- a/utilities/ovn-trace.c
>     +++ b/utilities/ovn-trace.c
>     @@ -2594,6 +2594,11 @@ trace_actions(const struct ovnact *ovnacts,
>     size_t ovnacts_len,
>                                     false, pipeline, super);
>                   break;
> 
>     +        case OVNACT_SCTP_ABORT:
>     +            execute_sctp_abort(ovnact_get_SCTP_ABORT(a), dp, uflow,
>     table_id,
>     +                               false, pipeline, super);
>     +            break;
>     +
>               case OVNACT_OVNFIELD_LOAD:
>                   execute_ovnfield_load(ovnact_get_OVNFIELD_LOAD(a), super);
>                   break;
>     -- 
>     2.29.2
> 
>     _______________________________________________
>     dev mailing list
>     dev at openvswitch.org <mailto:dev at openvswitch.org>
>     https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>     <https://mail.openvswitch.org/mailman/listinfo/ovs-dev>
> 



More information about the dev mailing list