[ovs-dev] Costumoized actions

Raul Suarez Marin raul.suarez.marin at gmail.com
Fri Mar 20 13:06:35 UTC 2015


Hello!

At the end I could make it work. I followed the steps of the actions
regarding ARP. I changed where to perform the commit_action function and
moved it to commit_set_nw_action. Now works perfectly. I do not know what
behaviour changes perform this change I did, but the thing that matters is
that it works now.

Kind regards and thank you for your help,
Raúl Suárez

2015-03-19 22:14 GMT+00:00 Jarno Rajahalme <jrajahalme at nicira.com>:

> Any custom actions need to be supported by the datapaths, otherwise they
> fail flow setup validation. Linux datapath (kernel module) is part of the
> linux kernel sources, but if you need to try out something you can test
> your feature with the userspace datapath first, then maybe with the
> ova-tree linux kernel module in the datapath directory.
>
> However, if you are adding support for a new packet header field (as
> hinted by MY_FIELD), you should not need to implement any new actions, as
> you should be able to use the set_field action.
>
>   Jarno
>
>
> On Mar 19, 2015, at 2:38 PM, Raul Suarez Marin <
> raul.suarez.marin at gmail.com> wrote:
>
> Thanks Jarno for the hints!
>
> I found this function looking for ", struct dpif_op " term in every file.
>
> static void dpif_linux_operate(struct dpif *dpif_, struct dpif_op **ops,
> size_t n_ops)
>
> The main lines in that function of my interest are:
> dpif_linux_encode_execute(dpif->dp_ifindex, execute, &aux->request);
> nl_transact_multiple(NETLINK_GENERIC, txnsp, n_ops);
>
> As I understand from this function, and following the path for op->type
> = DPIF_OP_EXECUTE, a request is sent at
> "nl_transact_multiple(NETLINK_GENERIC, txnsp, n_ops);" through
> NETLINK_GENERIC protocol (to the kernel?, any hint to where are they
> sent?). Inside this function, I can find these important functions:
>
> lib/netlink-socket.c:
> nl_sock_transact_multiple__(struct nl_sock *sock,
>                             struct nl_transaction **transactions, size_t n,
>                             size_t *done) {
> /* some lines */
> do {
>         error = sendmsg(sock->fd, &msg, 0) < 0 ? errno : 0;
> } while (error == EINTR);
>
> /* some lines */
>
> error = nl_sock_recv__(sock, buf_txn->reply, false);
>
> /* some lines */
>
> The thing is that when my action is performed, the error value is 0 (BAD,
> packet is not sent); and when it is not performed, error = 11 = EAGAIN (OK,
> actions are performed and packet is sent). I guess this means that whoever
> receives the request, still does not understand the meaning of the custom
> action I am creating.
>
> I will be posting here any updates I have.
>
> Kind regards,
> Raúl Suárez
>
>
> 2015-03-19 20:50 GMT+01:00 Jarno Rajahalme <jrajahalme at nicira.com>:
>
>> Raúl,
>>
>> The dip class functions are implemented by the different dip classes.
>> Linux and Windows data paths are interfaced by lib/dpif-netlink.c and the
>> userspace datapath is implemented in lib/dpif-netlink.c. You’ll find a
>> class struct with the local function pointers in those files, just search
>> for “operate” in those files.
>>
>> Hope this helps,
>>
>>   Jarno
>>
>> > On Mar 19, 2015, at 2:06 AM, Raul Suarez Marin <
>> raul.suarez.marin at gmail.com> wrote:
>> >
>> > Hello again,
>> >
>> > At lib/dpif.c in function "dpif_operate" there is a line that is being
>> > called.
>> > dpif->dpif_class->operate(dpif, ops, chunk);
>> >
>> > This is possibly the actions are performed, but I have no clue how to
>> know
>> > what function this line leads to.
>> >
>> > In lib/dpif-provider.h I can find the definition for these structs, but
>> I
>> > can only see:
>> >
>> > /* Executes each of the 'n_ops' operations in 'ops' on 'dpif', in the
>> order
>> > * in which they are specified, placing each operation's results in the
>> > * "output" members documented in comments.
>> > *
>> > * This function is optional.  It is only worthwhile to implement it if
>> > * 'dpif' can perform operations in batch faster than individually. */
>> > void (*operate)(struct dpif *dpif, struct dpif_op **ops, size_t n_ops);
>> >
>> > Kind regards,
>> > Raúl Suárez
>> >
>> > 2015-03-18 21:26 GMT+01:00 Raul Suarez Marin <
>> raul.suarez.marin at gmail.com>:
>> >
>> >> Hello Ben,
>> >>
>> >> Thank you for your answer. Let me correct myself when I said I adapated
>> >> parts of "handle_upcalls", I realized I just added debugging lines only
>> >> (my bad).
>> >> I am trying to do the ovs-vswitchd ofproto/trace command but I am
>> getting
>> >> failed connection attempts because "address family is not supported by
>> >> protocol". I will sort it out.
>> >>
>> >> My thoughts right now are:
>> >> 1) I have done in "do_xlate_actions" the part of reading the field I
>> want
>> >> to apply the action to. (new case OFPACT_MY_FIELD)
>> >> 2) I adapted "commit_odp_actions" which is called
>> >> by "compose_output_action" which is called by "xlate_output_action"
>> which
>> >> is called by "do_xlate_actions" (case OFPACT_OUTPUT) and it is located
>> in
>> >> "lib/ofp-util.c" This function adds the actions to the ofpbuf at
>> ctx->xout->odp_actions
>> >> with enum ovs_key = OVS_KEY_ATTR_MY_FIELD. I think there is no way this
>> >> fails (because it's just appending data).
>> >> 3) Added OVS_KEY_ATTR_MY_FIELD where needed. Specially in function
>> >> "odp_execute_set_action" at lib/ofp-execute.c, where looks like that
>> the
>> >> packet is actually modified. There, I do this:
>> >>
>> >> const struct ovs_key_STRUCTURE_MODEL my_key = nl_attr_get_unspec(a,
>> >> sizeof(struct ovs_key_STRUCTURE_MODEL))
>> >> struct MY_STRUCTURE *packet_to_do_action = ofpbuf_l3(packet);
>> >> packet_to_do_action ->my_field = my_key ->my_field;
>> >>
>> >> This should make it.
>> >>
>> >> BUT, HERE is the problem!
>> >>
>> >> I placed this code at "odp_execute_set_action" [function in 3)]
>> >>
>> >> FILE *f;
>> >> f = fopen("/home/raul/match_event2.txt", "ab+");
>> >> fprintf(f, "->odp_execute_set_action(%d)\n", type);
>> >> fclose(f);
>> >>
>> >> This is what I use for debugging. It is a very ugly way of doing it
>> but it
>> >> works for me. But, this line is not printed when debugging, so the code
>> >> never arrives at this point (even if my action is not implemented).
>> >> However, when my action is not implemented the action execution works,
>> but
>> >> still the said line is not printed... so maybe it executes that code
>> but it
>> >> is not able to print, I do not know really.
>> >>
>> >> I will be posting here updates so anyone trying to do this same thing
>> can
>> >> have a "clear" idea of what to do.
>> >>
>> >> Thanks again Ben for your help, hints and guidelines.
>> >>
>> >> Kind regards,
>> >> Raúl Suárez
>> >>
>> >>
>> >> 2015-03-12 16:06 GMT+01:00 Ben Pfaff <blp at nicira.com>:
>> >>
>> >>> On Thu, Mar 12, 2015 at 09:11:11AM +0100, Raul Suarez Marin wrote:
>> >>>> I am trying to develop new actions for openvswitch, I have done all
>> my
>> >>> work
>> >>>> but looks like it does not work.
>> >>>>
>> >>>> What I have done:
>> >>>> -> Enable ovs to read and parse new actions, so they appear on
>> ovs-ofctl
>> >>>> dump-flows command.
>> >>>> -> Adapted required parts of "handle_upcalls" function
>> >>>> at ofproto\ofproto-dpif-upcall.c (and inside functions)
>> >>>> -> Adapted "do_xlate_actions" function at
>> ofproto\ofproto-dpif-xlate.c
>> >>>>
>> >>>> The problem is:
>> >>>> If the new action is not programmed, everything goes as expected.
>> >>>> If the new action is programmed, no packet forwarding is done.
>> >>>>
>> >>>> The last sentence means that I have done all my work, but part of it
>> is
>> >>>> wrong, or that I am still missing something?
>> >>>
>> >>> I think you've hit the right parts of the code.  Try ofproto/trace
>> (see
>> >>> ovs-vswitchd(8)) for some hints.
>> >>>
>> >>> A new action wouldn't normally need any changes in handle_upcalls().
>> >>>
>> >>
>> >>
>> > _______________________________________________
>> > dev mailing list
>> > dev at openvswitch.org
>> > http://openvswitch.org/mailman/listinfo/dev
>>
>>
>
>



More information about the dev mailing list