On Wed, Nov 11, 2020 at 4:13 PM Eelco Chaudron <[email protected]> wrote:
>
> Add support for the dec_ttl action. Instead of programming the datapath with
> a flow that matches the packet TTL and an IP set, use a single dec_ttl action.
>
> The old behavior is kept if the new action is not supported by the datapath.
>
> # ovs-ofctl dump-flows br0
> cookie=0x0, duration=12.538s, table=0, n_packets=4, n_bytes=392, ip
> actions=dec_ttl,NORMAL
> cookie=0x0, duration=12.536s, table=0, n_packets=4, n_bytes=168,
> actions=NORMAL
>
> # ping -c1 -t 20 192.168.0.2
> PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data.
> IP (tos 0x0, ttl 19, id 45336, offset 0, flags [DF], proto ICMP (1), length
> 84)
> 192.168.0.1 > 192.168.0.2: ICMP echo request, id 8865, seq 1, length 64
>
> Linux netlink datapath support depends on upstream Linux commit:
> 744676e77720 ("openvswitch: add TTL decrement action")
>
>
> Note that in the Linux kernel tree the OVS_ACTION_ATTR_ADD_MPLS has been
> defined, and to make sure the IDs are in sync, it had to be added to the
> OVS source tree. This required some additional case statements, which
> should be revisited once the OVS implementation is added.
>
>
> Co-developed-by: Matteo Croce <[email protected]>
> Co-developed-by: Bindiya Kurle <[email protected]>
> Signed-off-by: Eelco Chaudron <[email protected]>
> ---
> datapath/linux/compat/include/linux/openvswitch.h | 8 ++
> lib/dpif-netdev.c | 4 +
> lib/dpif.c | 4 +
> lib/odp-execute.c | 102
> ++++++++++++++++++++-
> lib/odp-execute.h | 2
> lib/odp-util.c | 55 +++++++++++
> lib/packets.h | 13 ++-
> ofproto/ofproto-dpif-ipfix.c | 2
> ofproto/ofproto-dpif-sflow.c | 2
> ofproto/ofproto-dpif-xlate.c | 54 +++++++++--
> ofproto/ofproto-dpif.c | 37 ++++++++
> ofproto/ofproto-dpif.h | 6 +
> 12 files changed, 266 insertions(+), 23 deletions(-)
>
> diff --git a/datapath/linux/compat/include/linux/openvswitch.h
> b/datapath/linux/compat/include/linux/openvswitch.h
> index 2d884312f..66c386462 100644
> --- a/datapath/linux/compat/include/linux/openvswitch.h
> +++ b/datapath/linux/compat/include/linux/openvswitch.h
> @@ -1021,6 +1021,8 @@ enum ovs_action_attr {
> OVS_ACTION_ATTR_METER, /* u32 meter number. */
> OVS_ACTION_ATTR_CLONE, /* Nested OVS_CLONE_ATTR_*. */
> OVS_ACTION_ATTR_CHECK_PKT_LEN, /* Nested OVS_CHECK_PKT_LEN_ATTR_*. */
> + OVS_ACTION_ATTR_ADD_MPLS, /* struct ovs_action_add_mpls. */
> + OVS_ACTION_ATTR_DEC_TTL, /* Nested OVS_DEC_TTL_ATTR_*. */
>
> #ifndef __KERNEL__
> OVS_ACTION_ATTR_TUNNEL_PUSH, /* struct ovs_action_push_tnl*/
> @@ -1040,6 +1042,12 @@ enum ovs_action_attr {
>
> #define OVS_ACTION_ATTR_MAX (__OVS_ACTION_ATTR_MAX - 1)
>
> +enum ovs_dec_ttl_attr {
> + OVS_DEC_TTL_ATTR_UNSPEC,
> + OVS_DEC_TTL_ATTR_ACTION, /* Nested struct nlattr. */
> + __OVS_DEC_TTL_ATTR_MAX
> +};
> +
> /* Meters. */
> #define OVS_METER_FAMILY "ovs_meter"
> #define OVS_METER_MCGROUP "ovs_meter"
> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c
> index 300861ca5..35c6560c3 100644
> --- a/lib/dpif-netdev.c
> +++ b/lib/dpif-netdev.c
> @@ -7975,6 +7975,8 @@ dp_execute_cb(void *aux_, struct dp_packet_batch
> *packets_,
> case OVS_ACTION_ATTR_CT_CLEAR:
> case OVS_ACTION_ATTR_CHECK_PKT_LEN:
> case OVS_ACTION_ATTR_DROP:
> + case OVS_ACTION_ATTR_DEC_TTL:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> case __OVS_ACTION_ATTR_MAX:
> OVS_NOT_REACHED();
> }
> @@ -7991,7 +7993,7 @@ dp_netdev_execute_actions(struct dp_netdev_pmd_thread
> *pmd,
> struct dp_netdev_execute_aux aux = { pmd, flow };
>
> odp_execute_actions(&aux, packets, should_steal, actions,
> - actions_len, dp_execute_cb);
> + actions_len, dp_execute_cb, false);
> }
>
> struct dp_netdev_ct_dump {
> diff --git a/lib/dpif.c b/lib/dpif.c
> index ac2860764..644d32d47 100644
> --- a/lib/dpif.c
> +++ b/lib/dpif.c
> @@ -1273,6 +1273,8 @@ dpif_execute_helper_cb(void *aux_, struct
> dp_packet_batch *packets_,
> case OVS_ACTION_ATTR_UNSPEC:
> case OVS_ACTION_ATTR_CHECK_PKT_LEN:
> case OVS_ACTION_ATTR_DROP:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> + case OVS_ACTION_ATTR_DEC_TTL:
> case __OVS_ACTION_ATTR_MAX:
> OVS_NOT_REACHED();
> }
> @@ -1294,7 +1296,7 @@ dpif_execute_with_help(struct dpif *dpif, struct
> dpif_execute *execute)
>
> dp_packet_batch_init_packet(&pb, execute->packet);
> odp_execute_actions(&aux, &pb, false, execute->actions,
> - execute->actions_len, dpif_execute_helper_cb);
> + execute->actions_len, dpif_execute_helper_cb, false);
> return aux.error;
> }
>
> diff --git a/lib/odp-execute.c b/lib/odp-execute.c
> index 6eeda2a61..237776448 100644
> --- a/lib/odp-execute.c
> +++ b/lib/odp-execute.c
> @@ -716,7 +716,58 @@ odp_execute_sample(void *dp, struct dp_packet *packet,
> bool steal,
> }
> dp_packet_batch_init_packet(&pb, packet);
> odp_execute_actions(dp, &pb, true, nl_attr_get(subactions),
> - nl_attr_get_size(subactions), dp_execute_action);
> + nl_attr_get_size(subactions), dp_execute_action,
> + false);
> +}
> +
> +static bool execute_dec_ttl(struct dp_packet *packet)
> +{
> + struct eth_header *eth = dp_packet_eth(packet);
> +
> + if (dl_type_is_ipv4(eth->eth_type)) {
> + struct ip_header *nh = dp_packet_l3(packet);
> + uint8_t old_ttl = nh->ip_ttl;
> +
> + if (old_ttl <= 1) {
> + return true;
> + }
> +
> + nh->ip_ttl--;
> + nh->ip_csum = recalc_csum16(nh->ip_csum, htons(old_ttl << 8),
> + htons(nh->ip_ttl << 8));
> + } else if (dl_type_is_ipv6(eth->eth_type)) {
> + struct ovs_16aligned_ip6_hdr *nh = dp_packet_l3(packet);
> +
> + if (nh->ip6_hlim <= 1) {
> + return true;
> + }
> +
> + nh->ip6_hlim--;
> + }
> +
> + return false;
> +}
> +
> +static void odp_dec_ttl_exception_handler(void *dp,
> + struct dp_packet_batch *batch,
> + const struct nlattr *action,
> + odp_execute_cb dp_execute_action)
> +{
> + const struct nlattr *a;
> + const struct nlattr *subaction = NULL;
> + size_t left;
> +
> + if (nl_attr_is_valid(action, nl_attr_get_size(action))) {
> + dp_packet_delete_batch(batch, true);
> + return;
> + }
> +
> + NL_NESTED_FOR_EACH_UNSAFE (a, left, action) {
> + subaction = a;
> + odp_execute_actions(dp, batch, true, subaction,
> + nl_attr_get_size(subaction),
> + dp_execute_action, true);
> + }
> }
>
> static void
> @@ -734,11 +785,13 @@ odp_execute_clone(void *dp, struct dp_packet_batch
> *batch, bool steal,
> dp_packet_batch_clone(&clone_pkt_batch, batch);
> dp_packet_batch_reset_cutlen(batch);
> odp_execute_actions(dp, &clone_pkt_batch, true, nl_attr_get(actions),
> - nl_attr_get_size(actions), dp_execute_action);
> + nl_attr_get_size(actions), dp_execute_action,
> + false);
> }
> else {
> odp_execute_actions(dp, batch, true, nl_attr_get(actions),
> - nl_attr_get_size(actions), dp_execute_action);
> + nl_attr_get_size(actions), dp_execute_action,
> + false);
> }
> }
>
> @@ -783,7 +836,7 @@ odp_execute_check_pkt_len(void *dp, struct dp_packet
> *packet, bool steal,
> * odp_execute_actions. */
> dp_packet_batch_init_packet(&pb, packet);
> odp_execute_actions(dp, &pb, true, nl_attr_get(a), nl_attr_get_size(a),
> - dp_execute_action);
> + dp_execute_action, false);
> }
>
> static bool
> @@ -820,6 +873,8 @@ requires_datapath_assistance(const struct nlattr *a)
> case OVS_ACTION_ATTR_CT_CLEAR:
> case OVS_ACTION_ATTR_CHECK_PKT_LEN:
> case OVS_ACTION_ATTR_DROP:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> + case OVS_ACTION_ATTR_DEC_TTL:
> return false;
>
> case OVS_ACTION_ATTR_UNSPEC:
> @@ -846,7 +901,7 @@ requires_datapath_assistance(const struct nlattr *a)
> void
> odp_execute_actions(void *dp, struct dp_packet_batch *batch, bool steal,
> const struct nlattr *actions, size_t actions_len,
> - odp_execute_cb dp_execute_action)
> + odp_execute_cb dp_execute_action, bool force_last)
> {
> struct dp_packet *packet;
> const struct nlattr *a;
> @@ -864,7 +919,8 @@ odp_execute_actions(void *dp, struct dp_packet_batch
> *batch, bool steal,
>
> dp_execute_action(dp, batch, a, should_steal);
>
> - if (last_action || dp_packet_batch_is_empty(batch)) {
> + if (last_action || dp_packet_batch_is_empty(batch) ||
> + force_last) {
> /* We do not need to free the packets.
> * Either dp_execute_actions() has stolen them
> * or the batch is freed due to errors. In either
I don't remember the whole story, but I think that Ilya had some
concerns about force_last being redundant for 'steal'.
Sort of. Ilya, what's your opinion here?
> @@ -979,6 +1035,39 @@ odp_execute_actions(void *dp, struct dp_packet_batch
> *batch, bool steal,
> }
> break;
>
> + case OVS_ACTION_ATTR_DEC_TTL: {
> + const size_t cnt = dp_packet_batch_size(batch);
> + struct dp_packet_batch invalid_ttl;
> + size_t i;
> +
> + /* Make batch for invalid ttl packets. */
> + dp_packet_batch_init(&invalid_ttl);
> + invalid_ttl.trunc = batch->trunc;
> + invalid_ttl.do_not_steal = batch->do_not_steal;
> +
> + /* Add packets with ttl <=1 to the invalid_ttl batch
> + * and remove it from the batch. */
> + DP_PACKET_BATCH_REFILL_FOR_EACH (i, cnt, packet, batch) {
> + if (execute_dec_ttl(packet)) {
> + dp_packet_batch_add(&invalid_ttl, packet);
> + } else {
> + dp_packet_batch_refill(batch, packet, i);
> + }
> + }
> +
> + /* Execute action on packets with ttl <= 1. */
> + if (invalid_ttl.count > 0) {
> + odp_dec_ttl_exception_handler(dp, &invalid_ttl, a,
> + dp_execute_action);
> + }
> +
> + if (last_action || !batch->count) {
> + /* We do not need to free the packets. */
> + return;
> + }
> + break;
> + }
> +
> case OVS_ACTION_ATTR_TRUNC: {
> const struct ovs_action_trunc *trunc =
> nl_attr_get_unspec(a, sizeof *trunc);
> @@ -1077,6 +1166,7 @@ odp_execute_actions(void *dp, struct dp_packet_batch
> *batch, bool steal,
> case OVS_ACTION_ATTR_RECIRC:
> case OVS_ACTION_ATTR_CT:
> case OVS_ACTION_ATTR_UNSPEC:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> case __OVS_ACTION_ATTR_MAX:
> OVS_NOT_REACHED();
> }
> diff --git a/lib/odp-execute.h b/lib/odp-execute.h
> index a3578a575..3e80ed906 100644
> --- a/lib/odp-execute.h
> +++ b/lib/odp-execute.h
> @@ -38,5 +38,5 @@ typedef void (*odp_execute_cb)(void *dp, struct
> dp_packet_batch *batch,
> void odp_execute_actions(void *dp, struct dp_packet_batch *batch,
> bool steal,
> const struct nlattr *actions, size_t actions_len,
> - odp_execute_cb dp_execute_action);
> + odp_execute_cb dp_execute_action, bool force_last);
> #endif
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index 0bd2f9aa8..62b7739de 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -143,8 +143,10 @@ odp_action_len(uint16_t type)
> case OVS_ACTION_ATTR_POP_NSH: return 0;
> case OVS_ACTION_ATTR_CHECK_PKT_LEN: return ATTR_LEN_VARIABLE;
> case OVS_ACTION_ATTR_DROP: return sizeof(uint32_t);
> + case OVS_ACTION_ATTR_DEC_TTL: return ATTR_LEN_VARIABLE;
>
> case OVS_ACTION_ATTR_UNSPEC:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> case __OVS_ACTION_ATTR_MAX:
> return ATTR_LEN_INVALID;
> }
> @@ -1108,6 +1110,38 @@ format_odp_check_pkt_len_action(struct ds *ds, const
> struct nlattr *attr,
> portno_names);
> ds_put_cstr(ds, "))");
> }
> +static void
> +format_dec_ttl_action(struct ds *ds,const struct nlattr *attr,
> + const struct hmap *portno_names OVS_UNUSED)
> +{
> + const struct nlattr *nla_acts = NULL;
> + bool is_dp_netdev = false;
> +
> + if (attr->nla_len == 4) {
> + is_dp_netdev = true;
> + } else {
> + nla_acts = nl_attr_get(attr);
> + if (nla_acts->nla_type != 1) {
> + is_dp_netdev = true;
> + }
> + }
> +
> + ds_put_cstr(ds,"dec_ttl(ttl<=1(");
> + if (is_dp_netdev) {
Isn't it possible to encode the user and kernel actions in the same way?
> + if (attr->nla_len == 4) {
> + ds_put_format(ds, "drop");
> + } else {
> + format_odp_actions(ds, nla_acts, nla_acts->nla_len,
> portno_names);
> + }
> + } else {
> + int len = nl_attr_get_size(attr);
> +
> + len -= nl_attr_len_pad(nla_acts, len);
> + nla_acts = nl_attr_next(nla_acts);
> + format_odp_actions(ds, nla_acts, len, portno_names);
> + }
> + ds_put_format(ds, "))");
> +}
>
> static void
> format_odp_action(struct ds *ds, const struct nlattr *a,
> @@ -1256,7 +1290,11 @@ format_odp_action(struct ds *ds, const struct nlattr
> *a,
> case OVS_ACTION_ATTR_DROP:
> ds_put_cstr(ds, "drop");
> break;
> + case OVS_ACTION_ATTR_DEC_TTL:
> + format_dec_ttl_action(ds, a, portno_names);
> + break;
> case OVS_ACTION_ATTR_UNSPEC:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> case __OVS_ACTION_ATTR_MAX:
> default:
> format_generic_odp_action(ds, a);
> @@ -2498,6 +2536,23 @@ parse_odp_action__(struct parse_odp_context *context,
> const char *s,
> return n + 1;
> }
> }
> + {
> + if (!strncmp(s, "dec_ttl(ttl<=1(", 15)) {
> + size_t actions_ofs;
> + int n = 15;
> +
> + actions_ofs = nl_msg_start_nested(actions,
> + OVS_ACTION_ATTR_DEC_TTL);
> + int retval = parse_action_list(context, s + n, actions);
> + if (retval < 0) {
> + return retval;
> + }
> +
> + n += retval;
> + nl_msg_end_nested(actions, actions_ofs);
> + return n + 1;
> + }
> + }
>
> {
> if (!strncmp(s, "push_nsh(", 9)) {
> diff --git a/lib/packets.h b/lib/packets.h
> index 481bc22fa..b7fa7b121 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1211,10 +1211,19 @@ bool in6_is_lla(struct in6_addr *addr);
> void ipv6_multicast_to_ethernet(struct eth_addr *eth,
> const struct in6_addr *ip6);
>
> +static inline bool dl_type_is_ipv4(ovs_be16 dl_type)
> +{
> + return dl_type == htons(ETH_TYPE_IP);
> +}
> +
> +static inline bool dl_type_is_ipv6(ovs_be16 dl_type)
> +{
> + return dl_type == htons(ETH_TYPE_IPV6);
> +}
> +
> static inline bool dl_type_is_ip_any(ovs_be16 dl_type)
> {
> - return dl_type == htons(ETH_TYPE_IP)
> - || dl_type == htons(ETH_TYPE_IPV6);
> + return dl_type_is_ipv4(dl_type) || dl_type_is_ipv6(dl_type);
> }
>
> /* Tunnel header */
> diff --git a/ofproto/ofproto-dpif-ipfix.c b/ofproto/ofproto-dpif-ipfix.c
> index 796eb6f88..1c8e7ae26 100644
> --- a/ofproto/ofproto-dpif-ipfix.c
> +++ b/ofproto/ofproto-dpif-ipfix.c
> @@ -3018,6 +3018,8 @@ dpif_ipfix_read_actions(const struct flow *flow,
> case OVS_ACTION_ATTR_CHECK_PKT_LEN:
> case OVS_ACTION_ATTR_UNSPEC:
> case OVS_ACTION_ATTR_DROP:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> + case OVS_ACTION_ATTR_DEC_TTL:
> case __OVS_ACTION_ATTR_MAX:
> default:
> break;
> diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c
> index fdcb9eabb..c8bf6bee4 100644
> --- a/ofproto/ofproto-dpif-sflow.c
> +++ b/ofproto/ofproto-dpif-sflow.c
> @@ -1178,6 +1178,7 @@ dpif_sflow_read_actions(const struct flow *flow,
> case OVS_ACTION_ATTR_CT_CLEAR:
> case OVS_ACTION_ATTR_METER:
> case OVS_ACTION_ATTR_LB_OUTPUT:
> + case OVS_ACTION_ATTR_DEC_TTL:
> break;
>
> case OVS_ACTION_ATTR_SET_MASKED:
> @@ -1226,6 +1227,7 @@ dpif_sflow_read_actions(const struct flow *flow,
> case OVS_ACTION_ATTR_UNSPEC:
> case OVS_ACTION_ATTR_CHECK_PKT_LEN:
> case OVS_ACTION_ATTR_DROP:
> + case OVS_ACTION_ATTR_ADD_MPLS:
> case __OVS_ACTION_ATTR_MAX:
> default:
> break;
> diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
> index 11aa20754..a1fd1c752 100644
> --- a/ofproto/ofproto-dpif-xlate.c
> +++ b/ofproto/ofproto-dpif-xlate.c
> @@ -4839,9 +4839,12 @@ xlate_controller_action(struct xlate_ctx *ctx, int len,
> enum ofp_packet_in_reason reason,
> uint16_t controller_id,
> uint32_t provider_meter_id,
> - const uint8_t *userdata, size_t userdata_len)
> + const uint8_t *userdata, size_t userdata_len,
> + bool commit)
> {
> - xlate_commit_actions(ctx);
> + if (commit) {
> + xlate_commit_actions(ctx);
> + }
>
> /* A packet sent by an action in a table-miss rule is considered an
> * explicit table miss. OpenFlow before 1.3 doesn't have that concept so
> @@ -5087,7 +5090,8 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct
> ofpact_cnt_ids *ids)
>
> for (i = 0; i < ids->n_controllers; i++) {
> xlate_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
> - ids->cnt_ids[i], UINT32_MAX, NULL, 0);
> + ids->cnt_ids[i], UINT32_MAX, NULL, 0,
> + true);
> }
>
> /* Stop processing for current table. */
> @@ -5128,7 +5132,7 @@ compose_dec_nsh_ttl_action(struct xlate_ctx *ctx)
> return false;
> } else {
> xlate_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
> - 0, UINT32_MAX, NULL, 0);
> + 0, UINT32_MAX, NULL, 0, true);
> }
> }
>
> @@ -5161,7 +5165,7 @@ compose_dec_mpls_ttl_action(struct xlate_ctx *ctx)
> return false;
> } else {
> xlate_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0,
> - UINT32_MAX, NULL, 0);
> + UINT32_MAX, NULL, 0, true);
> }
> }
>
> @@ -5185,6 +5189,37 @@ xlate_delete_field(struct xlate_ctx *ctx,
> ds_destroy(&s);
> }
>
> +/* New handling for dec_ttl action. */
> +static void
> +xlate_dec_ttl_action(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
> +{
> + struct flow *flow = &ctx->xin->flow;
> + struct flow_wildcards *wc = ctx->wc;
> + size_t offset;
> + size_t i;
> +
> + if (!is_ip_any(flow)) {
> + return;
> + }
> +
> + if (!ctx->xbridge->support.dec_ttl_action) {
> + wc->masks.nw_ttl = 0xff;
> + compose_dec_ttl(ctx, ids);
> + return;
> + }
> +
> + xlate_commit_actions(ctx);
> + offset = nl_msg_start_nested(ctx->odp_actions, OVS_ACTION_ATTR_DEC_TTL);
> +
> + for (i = 0; i < ids->n_controllers; i++) {
> + xlate_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
> + ids->cnt_ids[i], UINT32_MAX, NULL, 0, false);
> + }
> +
> + nl_msg_end_nested(ctx->odp_actions, offset);
> + xlate_commit_actions(ctx);
> +}
> +
> /* Emits an action that outputs to 'port', within 'ctx'.
> *
> * 'controller_len' affects only packets sent to an OpenFlow controller. It
> @@ -5235,7 +5270,7 @@ xlate_output_action(struct xlate_ctx *ctx, ofp_port_t
> port,
> : group_bucket_action ? OFPR_GROUP
> : ctx->in_action_set ? OFPR_ACTION_SET
> : OFPR_ACTION),
> - 0, UINT32_MAX, NULL, 0);
> + 0, UINT32_MAX, NULL, 0, true);
> break;
> case OFPP_NONE:
> break;
> @@ -6796,7 +6831,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t
> ofpacts_len,
> controller->controller_id,
> controller->provider_meter_id,
> controller->userdata,
> - controller->userdata_len);
> + controller->userdata_len, true);
> }
> break;
>
> @@ -7004,10 +7039,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t
> ofpacts_len,
> break;
>
> case OFPACT_DEC_TTL:
> - wc->masks.nw_ttl = 0xff;
> - if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
> - return;
> - }
> + xlate_dec_ttl_action(ctx, ofpact_get_DEC_TTL(a));
> break;
>
> case OFPACT_NOTE:
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index fd0b2fdea..68e161e5f 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -1186,6 +1186,42 @@ check_trunc_action(struct dpif_backer *backer)
> return !error;
> }
>
> +/* Tests whether 'dpif' datapath supports decrement of the IP TTL via
> + * OVS_ACTION_DEC_TTL. */
> +static bool
> +check_dec_ttl_action(struct dpif *dpif)
> +{
> + uint8_t actbuf[NL_A_FLAG_SIZE];
> + struct odputil_keybuf keybuf;
> + struct flow flow = { 0 };
> + struct ofpbuf actions;
> + struct ofpbuf key;
> + bool supported;
> +
> + struct odp_flow_key_parms odp_parms = {
> + .flow = &flow,
> + .probe = true,
> + };
> +
> + ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
> + odp_flow_key_from_flow(&odp_parms, &key);
> +
> + ofpbuf_use_stack(&actions, &actbuf, sizeof actbuf);
> + nl_msg_put_flag(&actions, OVS_ACTION_ATTR_DEC_TTL);
> +
> + supported = dpif_probe_feature(dpif, "dec_ttl", &key, &actions, NULL);
> +
> + if (supported) {
> + VLOG_INFO("%s: Datapath supports dec_ttl action",
> + dpif_name(dpif));
> + } else {
> + VLOG_INFO("%s: Datapath does not support dec_ttl action",
> + dpif_name(dpif));
> + }
> +
> + return supported;
> +}
> +
> /* Tests whether 'backer''s datapath supports the clone action
> * OVS_ACTION_ATTR_CLONE. */
> static bool
> @@ -1590,6 +1626,7 @@ check_support(struct dpif_backer *backer)
> dpif_supports_explicit_drop_action(backer->dpif);
> backer->rt_support.lb_output_action=
> dpif_supports_lb_output_action(backer->dpif);
> + backer->rt_support.dec_ttl_action = check_dec_ttl_action(backer->dpif);
>
> /* Flow fields. */
> backer->rt_support.odp.ct_state = check_ct_state(backer);
> diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h
> index b41c3d82a..f4d1152bc 100644
> --- a/ofproto/ofproto-dpif.h
> +++ b/ofproto/ofproto-dpif.h
> @@ -204,7 +204,11 @@ struct group_dpif *group_dpif_lookup(struct ofproto_dpif
> *,
> DPIF_SUPPORT_FIELD(bool, explicit_drop_action, "Explicit Drop action") \
> \
> /* True if the datapath supports balance_tcp optimization */ \
> - DPIF_SUPPORT_FIELD(bool, lb_output_action, "Optimized Balance TCP mode")
> + DPIF_SUPPORT_FIELD(bool, lb_output_action, "Optimized Balance TCP mode")\
> + \
> + /* True if the datapath supports dec_ttl action. */ \
> + DPIF_SUPPORT_FIELD(bool, dec_ttl_action, "Decrement TTL action")
> +
>
>
> /* Stores the various features which the corresponding backer supports. */
>
For the remaining part, LGTM.
Regards,
--
per aspera ad upstream
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev