diff options
author | Simon Horman <horms@verge.net.au> | 2013-05-29 15:06:38 +0900 |
---|---|---|
committer | Ben Pfaff <blp@nicira.com> | 2013-05-29 13:13:34 -0700 |
commit | f094af7b17631ce688595d7cf70235a3eed9798c (patch) | |
tree | 1b4a72755325f3f65e514a0956a4b790ae34a99d /lib | |
parent | 81a114e557229fc4f0ced228626ff6f6e632ce6f (diff) | |
download | openvswitch-f094af7b17631ce688595d7cf70235a3eed9798c.tar.gz |
odp-execute: New module for executing datapath actions.
This moves generic action execution code out of lib/dpif-netedev.c
and into a new file, lib/odp-execute.c.
This is in preparation for using odp_execute_actions()
in lib/odp-util.c to handle recirculation/
Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/automake.mk | 2 | ||||
-rw-r--r-- | lib/dpif-netdev.c | 171 | ||||
-rw-r--r-- | lib/odp-execute.c | 200 | ||||
-rw-r--r-- | lib/odp-execute.h | 36 |
4 files changed, 246 insertions, 163 deletions
diff --git a/lib/automake.mk b/lib/automake.mk index f340c6070..bcaa1f8e5 100644 --- a/lib/automake.mk +++ b/lib/automake.mk @@ -100,6 +100,8 @@ lib_libopenvswitch_a_SOURCES = \ lib/netlink.h \ lib/nx-match.c \ lib/nx-match.h \ + lib/odp-execute.c \ + lib/odp-execute.h \ lib/odp-util.c \ lib/odp-util.h \ lib/ofp-actions.c \ diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index a4ac23f16..bd00f184f 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -42,6 +42,7 @@ #include "netdev.h" #include "netdev-vport.h" #include "netlink.h" +#include "odp-execute.h" #include "odp-util.h" #include "ofp-print.h" #include "ofpbuf.h" @@ -1095,18 +1096,9 @@ dpif_netdev_wait(struct dpif *dpif) } static void -dp_netdev_set_dl(struct ofpbuf *packet, const struct ovs_key_ethernet *eth_key) -{ - struct eth_header *eh = packet->l2; - - memcpy(eh->eth_src, eth_key->eth_src, sizeof eh->eth_src); - memcpy(eh->eth_dst, eth_key->eth_dst, sizeof eh->eth_dst); -} - -static void -dp_netdev_output_port(struct dp_netdev *dp, struct ofpbuf *packet, - uint32_t out_port) +dp_netdev_output_port(void *dp_, struct ofpbuf *packet, uint32_t out_port) { + struct dp_netdev *dp = dp_; struct dp_netdev_port *p = dp->ports[out_port]; if (p) { netdev_send(p->netdev, packet); @@ -1163,168 +1155,21 @@ dp_netdev_output_userspace(struct dp_netdev *dp, const struct ofpbuf *packet, } static void -dp_netdev_sample(struct dp_netdev *dp, - struct ofpbuf *packet, struct flow *key, - const struct nlattr *action) -{ - const struct nlattr *subactions = NULL; - const struct nlattr *a; - size_t left; - - NL_NESTED_FOR_EACH_UNSAFE (a, left, action) { - int type = nl_attr_type(a); - - switch ((enum ovs_sample_attr) type) { - case OVS_SAMPLE_ATTR_PROBABILITY: - if (random_uint32() >= nl_attr_get_u32(a)) { - return; - } - break; - - case OVS_SAMPLE_ATTR_ACTIONS: - subactions = a; - break; - - case OVS_SAMPLE_ATTR_UNSPEC: - case __OVS_SAMPLE_ATTR_MAX: - default: - NOT_REACHED(); - } - } - - dp_netdev_execute_actions(dp, packet, key, nl_attr_get(subactions), - nl_attr_get_size(subactions)); -} - -static void -dp_netdev_action_userspace(struct dp_netdev *dp, - struct ofpbuf *packet, const struct flow *key, - const struct nlattr *userdata) +dp_netdev_action_userspace(void *dp, struct ofpbuf *packet, + const struct flow *key, + const struct nlattr *userdata) { dp_netdev_output_userspace(dp, packet, DPIF_UC_ACTION, key, userdata); } static void -execute_set_action(struct ofpbuf *packet, const struct nlattr *a) -{ - enum ovs_key_attr type = nl_attr_type(a); - const struct ovs_key_ipv4 *ipv4_key; - const struct ovs_key_ipv6 *ipv6_key; - const struct ovs_key_tcp *tcp_key; - const struct ovs_key_udp *udp_key; - - switch (type) { - case OVS_KEY_ATTR_PRIORITY: - case OVS_KEY_ATTR_SKB_MARK: - case OVS_KEY_ATTR_TUNNEL: - /* not implemented */ - break; - - case OVS_KEY_ATTR_ETHERNET: - dp_netdev_set_dl(packet, - nl_attr_get_unspec(a, sizeof(struct ovs_key_ethernet))); - break; - - case OVS_KEY_ATTR_IPV4: - ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4)); - packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst, - ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl); - break; - - case OVS_KEY_ATTR_IPV6: - ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6)); - packet_set_ipv6(packet, ipv6_key->ipv6_proto, ipv6_key->ipv6_src, - ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass, - ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit); - break; - - case OVS_KEY_ATTR_TCP: - tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp)); - packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst); - break; - - case OVS_KEY_ATTR_UDP: - udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp)); - packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst); - break; - - case OVS_KEY_ATTR_MPLS: - set_mpls_lse(packet, nl_attr_get_be32(a)); - break; - - case OVS_KEY_ATTR_UNSPEC: - case OVS_KEY_ATTR_ENCAP: - case OVS_KEY_ATTR_ETHERTYPE: - case OVS_KEY_ATTR_IN_PORT: - case OVS_KEY_ATTR_VLAN: - case OVS_KEY_ATTR_ICMP: - case OVS_KEY_ATTR_ICMPV6: - case OVS_KEY_ATTR_ARP: - case OVS_KEY_ATTR_ND: - case __OVS_KEY_ATTR_MAX: - default: - NOT_REACHED(); - } -} - -static void dp_netdev_execute_actions(struct dp_netdev *dp, struct ofpbuf *packet, struct flow *key, const struct nlattr *actions, size_t actions_len) { - const struct nlattr *a; - unsigned int left; - - NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) { - int type = nl_attr_type(a); - - switch ((enum ovs_action_attr) type) { - case OVS_ACTION_ATTR_OUTPUT: - dp_netdev_output_port(dp, packet, nl_attr_get_u32(a)); - break; - - case OVS_ACTION_ATTR_USERSPACE: { - const struct nlattr *userdata; - - userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA); - dp_netdev_action_userspace(dp, packet, key, userdata); - break; - } - - case OVS_ACTION_ATTR_PUSH_VLAN: { - const struct ovs_action_push_vlan *vlan = nl_attr_get(a); - eth_push_vlan(packet, vlan->vlan_tci); - break; - } - - case OVS_ACTION_ATTR_POP_VLAN: - eth_pop_vlan(packet); - break; - - case OVS_ACTION_ATTR_PUSH_MPLS: { - const struct ovs_action_push_mpls *mpls = nl_attr_get(a); - push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse); - break; - } - - case OVS_ACTION_ATTR_POP_MPLS: - pop_mpls(packet, nl_attr_get_be16(a)); - break; - - case OVS_ACTION_ATTR_SET: - execute_set_action(packet, nl_attr_get(a)); - break; - - case OVS_ACTION_ATTR_SAMPLE: - dp_netdev_sample(dp, packet, key, a); - break; - - case OVS_ACTION_ATTR_UNSPEC: - case __OVS_ACTION_ATTR_MAX: - NOT_REACHED(); - } - } + odp_execute_actions(dp, packet, key, actions, actions_len, + dp_netdev_output_port, dp_netdev_action_userspace); } const struct dpif_class dpif_netdev_class = { diff --git a/lib/odp-execute.c b/lib/odp-execute.c new file mode 100644 index 000000000..b4a99a608 --- /dev/null +++ b/lib/odp-execute.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * Copyright (c) 2013 Simon Horman + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> +#include "odp-execute.h" +#include <linux/openvswitch.h> +#include <stdlib.h> +#include <string.h> + +#include "netlink.h" +#include "ofpbuf.h" +#include "packets.h" +#include "util.h" + +static void +odp_eth_set_addrs(struct ofpbuf *packet, const struct ovs_key_ethernet *eth_key) +{ + struct eth_header *eh = packet->l2; + + memcpy(eh->eth_src, eth_key->eth_src, sizeof eh->eth_src); + memcpy(eh->eth_dst, eth_key->eth_dst, sizeof eh->eth_dst); +} + +static void +odp_execute_set_action(struct ofpbuf *packet, const struct nlattr *a) +{ + enum ovs_key_attr type = nl_attr_type(a); + const struct ovs_key_ipv4 *ipv4_key; + const struct ovs_key_ipv6 *ipv6_key; + const struct ovs_key_tcp *tcp_key; + const struct ovs_key_udp *udp_key; + + switch (type) { + case OVS_KEY_ATTR_PRIORITY: + case OVS_KEY_ATTR_TUNNEL: + case OVS_KEY_ATTR_SKB_MARK: + /* not implemented */ + break; + + case OVS_KEY_ATTR_ETHERNET: + odp_eth_set_addrs(packet, + nl_attr_get_unspec(a, sizeof(struct ovs_key_ethernet))); + break; + + case OVS_KEY_ATTR_IPV4: + ipv4_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv4)); + packet_set_ipv4(packet, ipv4_key->ipv4_src, ipv4_key->ipv4_dst, + ipv4_key->ipv4_tos, ipv4_key->ipv4_ttl); + break; + + case OVS_KEY_ATTR_IPV6: + ipv6_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_ipv6)); + packet_set_ipv6(packet, ipv6_key->ipv6_proto, ipv6_key->ipv6_src, + ipv6_key->ipv6_dst, ipv6_key->ipv6_tclass, + ipv6_key->ipv6_label, ipv6_key->ipv6_hlimit); + break; + + case OVS_KEY_ATTR_TCP: + tcp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_tcp)); + packet_set_tcp_port(packet, tcp_key->tcp_src, tcp_key->tcp_dst); + break; + + case OVS_KEY_ATTR_UDP: + udp_key = nl_attr_get_unspec(a, sizeof(struct ovs_key_udp)); + packet_set_udp_port(packet, udp_key->udp_src, udp_key->udp_dst); + break; + + case OVS_KEY_ATTR_MPLS: + set_mpls_lse(packet, nl_attr_get_be32(a)); + break; + + case OVS_KEY_ATTR_UNSPEC: + case OVS_KEY_ATTR_ENCAP: + case OVS_KEY_ATTR_ETHERTYPE: + case OVS_KEY_ATTR_IN_PORT: + case OVS_KEY_ATTR_VLAN: + case OVS_KEY_ATTR_ICMP: + case OVS_KEY_ATTR_ICMPV6: + case OVS_KEY_ATTR_ARP: + case OVS_KEY_ATTR_ND: + case __OVS_KEY_ATTR_MAX: + default: + NOT_REACHED(); + } +} + +static void +odp_execute_sample(void *dp, struct ofpbuf *packet, struct flow *key, + const struct nlattr *action, + void (*output)(void *dp, struct ofpbuf *packet, + uint32_t out_port), + void (*userspace)(void *dp, struct ofpbuf *packet, + const struct flow *key, + const struct nlattr *a)) +{ + const struct nlattr *subactions = NULL; + const struct nlattr *a; + size_t left; + + NL_NESTED_FOR_EACH_UNSAFE (a, left, action) { + int type = nl_attr_type(a); + + switch ((enum ovs_sample_attr) type) { + case OVS_SAMPLE_ATTR_PROBABILITY: + if (random_uint32() >= nl_attr_get_u32(a)) { + return; + } + break; + + case OVS_SAMPLE_ATTR_ACTIONS: + subactions = a; + break; + + case OVS_SAMPLE_ATTR_UNSPEC: + case __OVS_SAMPLE_ATTR_MAX: + default: + NOT_REACHED(); + } + } + + odp_execute_actions(dp, packet, key, nl_attr_get(subactions), + nl_attr_get_size(subactions), output, userspace); +} + +void +odp_execute_actions(void *dp, struct ofpbuf *packet, struct flow *key, + const struct nlattr *actions, size_t actions_len, + void (*output)(void *dp, struct ofpbuf *packet, + uint32_t out_port), + void (*userspace)(void *dp, struct ofpbuf *packet, + const struct flow *key, + const struct nlattr *a)) +{ + const struct nlattr *a; + unsigned int left; + + NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) { + int type = nl_attr_type(a); + + switch ((enum ovs_action_attr) type) { + case OVS_ACTION_ATTR_OUTPUT: + output(dp, packet, nl_attr_get_u32(a)); + break; + + case OVS_ACTION_ATTR_USERSPACE: { + const struct nlattr *userdata; + + userdata = nl_attr_find_nested(a, OVS_USERSPACE_ATTR_USERDATA); + userspace(dp, packet, key, userdata); + break; + } + + case OVS_ACTION_ATTR_PUSH_VLAN: { + const struct ovs_action_push_vlan *vlan = nl_attr_get(a); + eth_push_vlan(packet, vlan->vlan_tci); + break; + } + + case OVS_ACTION_ATTR_POP_VLAN: + eth_pop_vlan(packet); + break; + + case OVS_ACTION_ATTR_PUSH_MPLS: { + const struct ovs_action_push_mpls *mpls = nl_attr_get(a); + push_mpls(packet, mpls->mpls_ethertype, mpls->mpls_lse); + break; + } + + case OVS_ACTION_ATTR_POP_MPLS: + pop_mpls(packet, nl_attr_get_be16(a)); + break; + + case OVS_ACTION_ATTR_SET: + odp_execute_set_action(packet, nl_attr_get(a)); + break; + + case OVS_ACTION_ATTR_SAMPLE: + odp_execute_sample(dp, packet, key, a, output, userspace); + break; + + case OVS_ACTION_ATTR_UNSPEC: + case __OVS_ACTION_ATTR_MAX: + NOT_REACHED(); + } + } +} diff --git a/lib/odp-execute.h b/lib/odp-execute.h new file mode 100644 index 000000000..89dd66bd4 --- /dev/null +++ b/lib/odp-execute.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Nicira, Inc. + * Copyright (c) 2013 Simon Horman + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef EXECUTE_ACTIONS_H +#define EXECUTE_ACTIONS_H 1 + +#include <stddef.h> +#include <stdint.h> + +struct flow; +struct nlattr; +struct ofpbuf; + +void +odp_execute_actions(void *dp, struct ofpbuf *packet, struct flow *key, + const struct nlattr *actions, size_t actions_len, + void (*output)(void *dp, struct ofpbuf *packet, + uint32_t out_port), + void (*userspace)(void *dp, struct ofpbuf *packet, + const struct flow *key, + const struct nlattr *a)); +#endif |