[ovs-dev] [classifier-opt 10/28] ofproto: Move ofpacts_check() calls from ofproto-dpif to ofproto.

Ethan Jackson ethan at nicira.com
Tue Aug 7 19:44:52 UTC 2012


I don't feel particularly strongly about it.  The current
implementation is fine with me.

Ethan

On Tue, Aug 7, 2012 at 12:40 PM, Ben Pfaff <blp at nicira.com> wrote:
> I think you and I might have slightly different models in mind.  The
> model that I'm after at the moment is that the ofproto generic layer
> checks that a set of actions is valid (which can be done without
> knowing anything about the hardware) and then the implementation
> checks that it can actually implement those valid actions.
>
> I agree that the approach you suggest would work too, and that it
> could work with either the model I have in mind or a model where the
> implementation has to do all of the validation as well as the
> implement-ability checking.
>
> So, I'm inclined to leave it the way I have it, but I remain open to
> further discussion.
>
> On Mon, Jul 30, 2012 at 02:45:26PM -0700, Ethan Jackson wrote:
>> Looks good to me.
>>
>> I had a thought but I don't feel strongly about it.  What if we made a
>> new hook for ofproto implementations:
>>
>> enum ofperr (*validate_actions)(const struct ofpact ofpacts[], size_t
>> ofpacts_len, const struct flow *, int max_ports).
>>
>> In the ofproto-dpif implementation this would simply pass through to
>> ofpacts_check(), but in other implementations it could reject action
>> lists which are not implementable by their dpif.  This would allow us
>> to make *packet_out() and *rule_construct() assume that the actions
>> are both valid and implementable.  Then they could return void instead
>> of an ofperr.  Also if we did this, rule_modify_actions() may be
>> completely unnecessary.  The complete_operation() calls could be
>> pulled into ofproto.
>>
>> At any rate, this seems marginally cleaner to me, but you may feel
>> strongly in the other direction in which case the current approach is
>> fine.
>>
>> Ethan
>>
>> On Fri, Jul 20, 2012 at 4:25 PM, Ben Pfaff <blp at nicira.com> wrote:
>> > Signed-off-by: Ben Pfaff <blp at nicira.com>
>> > ---
>> >  ofproto/ofproto-dpif.c     |   58 ++++++++++++++-----------------------------
>> >  ofproto/ofproto-provider.h |   14 ++++-------
>> >  ofproto/ofproto.c          |   16 +++++++++---
>> >  3 files changed, 36 insertions(+), 52 deletions(-)
>> >
>> > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
>> > index f1d2ae0..44cbd17 100644
>> > --- a/ofproto/ofproto-dpif.c
>> > +++ b/ofproto/ofproto-dpif.c
>> > @@ -4592,13 +4592,6 @@ rule_construct(struct rule *rule_)
>> >      struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
>> >      struct rule_dpif *victim;
>> >      uint8_t table_id;
>> > -    enum ofperr error;
>> > -
>> > -    error = ofpacts_check(rule->up.ofpacts, rule->up.ofpacts_len,
>> > -                          &rule->up.cr.flow, ofproto->up.max_ports);
>> > -    if (error) {
>> > -        return error;
>> > -    }
>> >
>> >      rule->packet_count = 0;
>> >      rule->byte_count = 0;
>> > @@ -4701,15 +4694,6 @@ static void
>> >  rule_modify_actions(struct rule *rule_)
>> >  {
>> >      struct rule_dpif *rule = rule_dpif_cast(rule_);
>> > -    struct ofproto_dpif *ofproto = ofproto_dpif_cast(rule->up.ofproto);
>> > -    enum ofperr error;
>> > -
>> > -    error = ofpacts_check(rule->up.ofpacts, rule->up.ofpacts_len,
>> > -                          &rule->up.cr.flow, ofproto->up.max_ports);
>> > -    if (error) {
>> > -        ofoperation_complete(rule->up.pending, error);
>> > -        return;
>> > -    }
>> >
>> >      complete_operation(rule);
>> >  }
>> > @@ -6359,36 +6343,32 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet,
>> >             const struct ofpact *ofpacts, size_t ofpacts_len)
>> >  {
>> >      struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
>> > -    enum ofperr error;
>> > +    struct odputil_keybuf keybuf;
>> > +    struct dpif_flow_stats stats;
>> >
>> > -    error = ofpacts_check(ofpacts, ofpacts_len, flow, ofproto->up.max_ports);
>> > -    if (!error) {
>> > -        struct odputil_keybuf keybuf;
>> > -        struct dpif_flow_stats stats;
>> > +    struct ofpbuf key;
>> >
>> > -        struct ofpbuf key;
>> > +    struct action_xlate_ctx ctx;
>> > +    uint64_t odp_actions_stub[1024 / 8];
>> > +    struct ofpbuf odp_actions;
>> >
>> > -        struct action_xlate_ctx ctx;
>> > -        uint64_t odp_actions_stub[1024 / 8];
>> > -        struct ofpbuf odp_actions;
>> > +    ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
>> > +    odp_flow_key_from_flow(&key, flow);
>> >
>> > -        ofpbuf_use_stack(&key, &keybuf, sizeof keybuf);
>> > -        odp_flow_key_from_flow(&key, flow);
>> > +    dpif_flow_stats_extract(flow, packet, &stats);
>> >
>> > -        dpif_flow_stats_extract(flow, packet, &stats);
>> > +    action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL,
>> > +                          packet_get_tcp_flags(packet, flow), packet);
>> > +    ctx.resubmit_stats = &stats;
>> >
>> > -        action_xlate_ctx_init(&ctx, ofproto, flow, flow->vlan_tci, NULL,
>> > -                              packet_get_tcp_flags(packet, flow), packet);
>> > -        ctx.resubmit_stats = &stats;
>> > +    ofpbuf_use_stub(&odp_actions,
>> > +                    odp_actions_stub, sizeof odp_actions_stub);
>> > +    xlate_actions(&ctx, ofpacts, ofpacts_len, &odp_actions);
>> > +    dpif_execute(ofproto->dpif, key.data, key.size,
>> > +                 odp_actions.data, odp_actions.size, packet);
>> > +    ofpbuf_uninit(&odp_actions);
>> >
>> > -        ofpbuf_use_stub(&odp_actions,
>> > -                        odp_actions_stub, sizeof odp_actions_stub);
>> > -        xlate_actions(&ctx, ofpacts, ofpacts_len, &odp_actions);
>> > -        dpif_execute(ofproto->dpif, key.data, key.size,
>> > -                     odp_actions.data, odp_actions.size, packet);
>> > -        ofpbuf_uninit(&odp_actions);
>> > -    }
>> > -    return error;
>> > +    return 0;
>> >  }
>> >
>> >  /* NetFlow. */
>> > diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h
>> > index 2f62473..80cd55f 100644
>> > --- a/ofproto/ofproto-provider.h
>> > +++ b/ofproto/ofproto-provider.h
>> > @@ -803,11 +803,7 @@ struct ofproto_class {
>> >       *     registers, then it is an error if 'rule->cr' does not wildcard all
>> >       *     registers.
>> >       *
>> > -     *   - Validate that 'rule->ofpacts' is a sequence of well-formed actions
>> > -     *     that the datapath can correctly implement.  If your ofproto
>> > -     *     implementation only implements a subset of the actions that Open
>> > -     *     vSwitch understands, then you should implement your own action
>> > -     *     validation.
>> > +     *   - Validate that the datapath can correctly implement 'rule->ofpacts'.
>> >       *
>> >       *   - If the rule is valid, update the datapath flow table, adding the new
>> >       *     rule or replacing the existing one.
>> > @@ -889,8 +885,8 @@ struct ofproto_class {
>> >       *
>> >       * ->rule_modify_actions() should set the following in motion:
>> >       *
>> > -     *   - Validate that the actions now in 'rule' are well-formed OpenFlow
>> > -     *     actions that the datapath can correctly implement.
>> > +     *   - Validate that the datapath can correctly implement the actions now
>> > +     *     in 'rule'.
>> >       *
>> >       *   - Update the datapath flow table with the new actions.
>> >       *
>> > @@ -943,8 +939,8 @@ struct ofproto_class {
>> >       * The caller retains ownership of 'packet' and of 'ofpacts', so
>> >       * ->packet_out() should not modify or free them.
>> >       *
>> > -     * This function must validate that it can implement 'ofpacts'.  If not,
>> > -     * then it should return an OpenFlow error code.
>> > +     * This function must validate that it can correctly implement 'ofpacts'.
>> > +     * If not, then it should return an OpenFlow error code.
>> >       *
>> >       * 'flow' reflects the flow information for 'packet'.  All of the
>> >       * information in 'flow' is extracted from 'packet', except for
>> > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c
>> > index cbcf0d2..17131ca 100644
>> > --- a/ofproto/ofproto.c
>> > +++ b/ofproto/ofproto.c
>> > @@ -2138,10 +2138,13 @@ handle_packet_out(struct ofconn *ofconn, const struct ofp_packet_out *opo)
>> >          ofpbuf_use_const(payload, po.packet, po.packet_len);
>> >      }
>> >
>> > -    /* Send out packet. */
>> > +    /* Verify actions against packet, then send packet if successful. */
>> >      flow_extract(payload, 0, 0, po.in_port, &flow);
>> > -    error = p->ofproto_class->packet_out(p, payload, &flow,
>> > -                                         po.ofpacts, po.ofpacts_len);
>> > +    error = ofpacts_check(po.ofpacts, po.ofpacts_len, &flow, p->max_ports);
>> > +    if (!error) {
>> > +        error = p->ofproto_class->packet_out(p, payload, &flow,
>> > +                                             po.ofpacts, po.ofpacts_len);
>> > +    }
>> >      ofpbuf_delete(payload);
>> >
>> >  exit_free_ofpacts:
>> > @@ -3237,7 +3240,12 @@ handle_flow_mod(struct ofconn *ofconn, const struct ofp_header *oh)
>> >           * dropped from OpenFlow in the near future.  There is no good error
>> >           * code, so just state that the flow table is full. */
>> >          error = OFPERR_OFPFMFC_ALL_TABLES_FULL;
>> > -    } else {
>> > +    }
>> > +    if (!error) {
>> > +        error = ofpacts_check(fm.ofpacts, fm.ofpacts_len,
>> > +                              &fm.cr.flow, ofproto->max_ports);
>> > +    }
>> > +    if (!error) {
>> >          error = handle_flow_mod__(ofconn_get_ofproto(ofconn), ofconn, &fm, oh);
>> >      }
>> >      if (error) {
>> > --
>> > 1.7.2.5
>> >



More information about the dev mailing list