[ovs-dev] [PATCH 2/2] ofproto: Translate NXAST_SAMPLE actions into SAMPLE datapath actions

Romain Lenglet rlenglet at vmware.com
Tue Dec 11 06:12:57 UTC 2012


I noticed this patch doesn't correctly handle the case of a zero sampling probability.
I'll fix that by not translating the action in that case, and re-send a patch.
--
Romain Lenglet

----- Original Message -----
> From: "Romain Lenglet" <rlenglet at vmware.com>
> To: dev at openvswitch.org
> Cc: "Romain Lenglet" <rlenglet at vmware.com>
> Sent: Monday, December 10, 2012 3:24:06 PM
> Subject: [PATCH 2/2] ofproto: Translate NXAST_SAMPLE actions into SAMPLE datapath actions
> 
> ---
>  lib/odp-util.c         | 14 ++++++++
>  lib/odp-util.h         |  9 +++++-
>  ofproto/ofproto-dpif.c | 86
>  ++++++++++++++++++++++++++++++++++++++++----------
>  tests/odp.at           |  1 +
>  4 files changed, 93 insertions(+), 17 deletions(-)
> 
> diff --git a/lib/odp-util.c b/lib/odp-util.c
> index de97fd2..50feeb5 100644
> --- a/lib/odp-util.c
> +++ b/lib/odp-util.c
> @@ -279,6 +279,11 @@ format_odp_userspace_action(struct ds *ds, const
> struct nlattr *attr)
>              ds_put_format(ds, ")");
>              break;
>  
> +        case USER_ACTION_COOKIE_IPFIX:
> +            ds_put_format(ds, ",IPFIX(obs_point_id=%"PRIu32")",
> +                          cookie.ipfix.obs_point_id);
> +            break;
> +
>          case USER_ACTION_COOKIE_UNSPEC:
>          default:
>              ds_put_format(ds, ",userdata=0x%"PRIx64, userdata);
> @@ -419,6 +424,7 @@ parse_odp_action(const char *s, const struct
> simap *port_names,
>      {
>          unsigned long long int pid;
>          unsigned long long int output;
> +        unsigned long long int obs_point_id;
>          char userdata_s[32];
>          int vid, pcp;
>          int n = -1;
> @@ -464,6 +470,14 @@ parse_odp_action(const char *s, const struct
> simap *port_names,
>  
>              odp_put_userspace_action(pid, &cookie, actions);
>              return n;
> +        } else if (sscanf(s,
> "userspace(pid=%lli,IPFIX(obs_point_id=%lli))%n",
> +                          &pid, &obs_point_id, &n) > 0 && n > 0) {
> +            union user_action_cookie cookie;
> +
> +            cookie.type = USER_ACTION_COOKIE_IPFIX;
> +            cookie.ipfix.obs_point_id = obs_point_id;
> +            odp_put_userspace_action(pid, &cookie, actions);
> +            return n;
>          } else if (sscanf(s, "userspace(pid=%lli,userdata="
>                            "%31[x0123456789abcdefABCDEF])%n", &pid,
>                            userdata_s,
>                            &n) > 0 && n > 0) {
> diff --git a/lib/odp-util.h b/lib/odp-util.h
> index 9d38f33..44cde1d 100644
> --- a/lib/odp-util.h
> +++ b/lib/odp-util.h
> @@ -119,7 +119,8 @@ void commit_odp_actions(const struct flow *,
> struct flow *base,
>  enum user_action_cookie_type {
>      USER_ACTION_COOKIE_UNSPEC,
>      USER_ACTION_COOKIE_SFLOW,        /* Packet for sFlow sampling.
>      */
> -    USER_ACTION_COOKIE_SLOW_PATH     /* Userspace must process this
> flow. */
> +    USER_ACTION_COOKIE_SLOW_PATH,    /* Userspace must process this
> flow. */
> +    USER_ACTION_COOKIE_IPFIX         /* Packet for IPFIX sampling.
> */
>  };
>  
>  /* user_action_cookie is passed as argument to
>  OVS_ACTION_ATTR_USERSPACE.
> @@ -138,6 +139,12 @@ union user_action_cookie {
>          uint16_t unused;
>          uint32_t reason;        /* enum slow_path_reason. */
>      } slow_path;
> +
> +    struct {
> +        uint16_t type;          /* USER_ACTION_COOKIE_IPFIX. */
> +        uint16_t unused;
> +        uint32_t obs_point_id;  /* Observation Point ID. */
> +    } ipfix;
>  };
>  BUILD_ASSERT_DECL(sizeof(union user_action_cookie) == 8);
>  
> diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
> index 854ad29..c585038 100644
> --- a/ofproto/ofproto-dpif.c
> +++ b/ofproto/ofproto-dpif.c
> @@ -3552,7 +3552,7 @@ handle_miss_upcalls(struct dpif_backer *backer,
> struct dpif_upcall *upcalls,
>      hmap_destroy(&todo);
>  }
>  
> -static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL }
> +static enum { SFLOW_UPCALL, MISS_UPCALL, BAD_UPCALL, IPFIX_UPCALL }
>  classify_upcall(const struct dpif_upcall *upcall)
>  {
>      union user_action_cookie cookie;
> @@ -3580,6 +3580,9 @@ classify_upcall(const struct dpif_upcall
> *upcall)
>      case USER_ACTION_COOKIE_SLOW_PATH:
>          return MISS_UPCALL;
>  
> +    case USER_ACTION_COOKIE_IPFIX:
> +        return IPFIX_UPCALL;
> +
>      case USER_ACTION_COOKIE_UNSPEC:
>      default:
>          VLOG_WARN_RL(&rl, "invalid user cookie : 0x%"PRIx64,
>          upcall->userdata);
> @@ -3624,6 +3627,13 @@ handle_sflow_upcall(struct dpif_backer
> *backer,
>                          odp_in_port, &cookie);
>  }
>  
> +static void
> +handle_ipfix_upcall(struct dpif_backer *backer OVS_UNUSED,
> +                    const struct dpif_upcall *upcall OVS_UNUSED)
> +{
> +    /* TODO: Send an IPFIX sample. */
> +}
> +
>  static int
>  handle_upcalls(struct dpif_backer *backer, unsigned int max_batch)
>  {
> @@ -3661,6 +3671,11 @@ handle_upcalls(struct dpif_backer *backer,
> unsigned int max_batch)
>              ofpbuf_uninit(buf);
>              break;
>  
> +        case IPFIX_UPCALL:
> +            handle_ipfix_upcall(backer, upcall);
> +            ofpbuf_uninit(buf);
> +            break;
> +
>          case BAD_UPCALL:
>              ofpbuf_uninit(buf);
>              break;
> @@ -5268,6 +5283,30 @@ put_userspace_action(const struct ofproto_dpif
> *ofproto,
>      return odp_put_userspace_action(pid, cookie, odp_actions);
>  }
>  
> +/* Compose SAMPLE action for sFlow or IPFIX. */
> +static size_t
> +compose_sample_action(const struct ofproto_dpif *ofproto,
> +                      struct ofpbuf *odp_actions,
> +                      const struct flow *flow,
> +                      const uint32_t probability,
> +                      const union user_action_cookie *cookie)
> +{
> +    size_t sample_offset, actions_offset;
> +    int cookie_offset;
> +
> +    sample_offset = nl_msg_start_nested(odp_actions,
> OVS_ACTION_ATTR_SAMPLE);
> +
> +    /* Number of packets out of UINT_MAX to sample. */
> +    nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY,
> probability);
> +
> +    actions_offset = nl_msg_start_nested(odp_actions,
> OVS_SAMPLE_ATTR_ACTIONS);
> +    cookie_offset = put_userspace_action(ofproto, odp_actions, flow,
> cookie);
> +
> +    nl_msg_end_nested(odp_actions, actions_offset);
> +    nl_msg_end_nested(odp_actions, sample_offset);
> +    return cookie_offset;
> +}
> +
>  static void
>  compose_sflow_cookie(const struct ofproto_dpif *ofproto,
>                       ovs_be16 vlan_tci, uint32_t odp_port,
> @@ -5309,27 +5348,24 @@ compose_sflow_action(const struct
> ofproto_dpif *ofproto,
>  {
>      uint32_t probability;
>      union user_action_cookie cookie;
> -    size_t sample_offset, actions_offset;
> -    int cookie_offset;
>  
>      if (!ofproto->sflow || flow->in_port == OFPP_NONE) {
>          return 0;
>      }
>  
> -    sample_offset = nl_msg_start_nested(odp_actions,
> OVS_ACTION_ATTR_SAMPLE);
> -
> -    /* Number of packets out of UINT_MAX to sample. */
>      probability = dpif_sflow_get_probability(ofproto->sflow);
> -    nl_msg_put_u32(odp_actions, OVS_SAMPLE_ATTR_PROBABILITY,
> probability);
> -
> -    actions_offset = nl_msg_start_nested(odp_actions,
> OVS_SAMPLE_ATTR_ACTIONS);
>      compose_sflow_cookie(ofproto, htons(0), odp_port,
>                           odp_port == OVSP_NONE ? 0 : 1, &cookie);
> -    cookie_offset = put_userspace_action(ofproto, odp_actions, flow,
> &cookie);
>  
> -    nl_msg_end_nested(odp_actions, actions_offset);
> -    nl_msg_end_nested(odp_actions, sample_offset);
> -    return cookie_offset;
> +    return compose_sample_action(ofproto, odp_actions, flow,
>  probability,
> +                                 &cookie);
> +}
> +
> +static void
> +compose_ipfix_cookie(uint32_t obs_point_id, union user_action_cookie
> *cookie)
> +{
> +    cookie->type = USER_ACTION_COOKIE_IPFIX;
> +    cookie->ipfix.obs_point_id = obs_point_id;
>  }
>  
>  /* SAMPLE action must be first action in any given list of actions.
> @@ -5841,6 +5877,16 @@ xlate_fin_timeout(struct action_xlate_ctx
> *ctx,
>      }
>  }
>  
> +static void
> +xlate_sample_action(struct action_xlate_ctx *ctx,
> +                    const struct ofpact_sample *os)
> +{
> +    union user_action_cookie cookie;
> +    compose_ipfix_cookie(os->obs_point_id, &cookie);
> +    compose_sample_action(ctx->ofproto, ctx->odp_actions,
> &ctx->flow,
> +                          os->probability, &cookie);
> +}
> +
>  static bool
>  may_receive(const struct ofport_dpif *port, struct action_xlate_ctx
>  *ctx)
>  {
> @@ -5869,6 +5915,7 @@ do_xlate_actions(const struct ofpact *ofpacts,
> size_t ofpacts_len,
>      const struct ofport_dpif *port;
>      bool was_evictable = true;
>      const struct ofpact *a;
> +    int non_sample_actions_count = 0;
>  
>      port = get_ofp_port(ctx->ofproto, ctx->flow.in_port);
>      if (port && !may_receive(port, ctx)) {
> @@ -6053,11 +6100,18 @@ do_xlate_actions(const struct ofpact
> *ofpacts, size_t ofpacts_len,
>          }
>  
>          case OFPACT_SAMPLE:
> -            /* TODO: Check that SAMPLE actions are always the first
> -             * actions in a flow. */
> -            /* TODO: Actually implement the translation here. */
> +            /* SAMPLE actions should be the first in a flow's
> actions. */
> +            if (non_sample_actions_count > 0) {
> +                VLOG_WARN_RL(&rl,
> +                             "sample action not at beginning of
> action list");
> +            }
> +            xlate_sample_action(ctx, ofpact_get_SAMPLE(a));
>              break;
>          }
> +
> +        if (a->type != OFPACT_SAMPLE) {
> +            non_sample_actions_count++;
> +        }
>      }
>  
>  out:
> diff --git a/tests/odp.at b/tests/odp.at
> index a5f6dbe..bcc32bf 100644
> --- a/tests/odp.at
> +++ b/tests/odp.at
> @@ -76,6 +76,7 @@ userspace(pid=9765,slow_path())
>  userspace(pid=9765,slow_path(cfm))
>  userspace(pid=9765,slow_path(cfm,match))
>  userspace(pid=9123,userdata=0x815309)
> +userspace(pid=6633,IPFIX(obs_point_id=12345))
>  set(tun_id(0x7f10354))
>  set(in_port(2))
>  set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))
> --
> 1.8.0.1
> 
> 



More information about the dev mailing list