2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-17 14:28:02 +00:00

odp-util: Move commit_odp_actions() from ofproto-dpif.

In an effort to simplify ofproto-dpif, this commit moves the
definition of commit_odp_actions() to odp-util.
This commit is contained in:
Ethan Jackson
2011-11-28 14:14:23 -08:00
parent ecfcbf515d
commit 5bbda0aab1
3 changed files with 166 additions and 161 deletions

View File

@@ -1721,3 +1721,164 @@ odp_put_userspace_action(uint32_t pid, const struct user_action_cookie *cookie,
return cookie ? odp_actions->size - NLA_ALIGN(sizeof *cookie) : 0;
}
/* The commit_odp_actions() function and its helpers. */
static void
commit_set_action(struct ofpbuf *odp_actions, enum ovs_key_attr key_type,
const void *key, size_t key_size)
{
size_t offset = nl_msg_start_nested(odp_actions, OVS_ACTION_ATTR_SET);
nl_msg_put_unspec(odp_actions, key_type, key, key_size);
nl_msg_end_nested(odp_actions, offset);
}
static void
commit_set_tun_id_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
if (base->tun_id == flow->tun_id) {
return;
}
base->tun_id = flow->tun_id;
commit_set_action(odp_actions, OVS_KEY_ATTR_TUN_ID,
&base->tun_id, sizeof(base->tun_id));
}
static void
commit_set_ether_addr_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
struct ovs_key_ethernet eth_key;
if (eth_addr_equals(base->dl_src, flow->dl_src) &&
eth_addr_equals(base->dl_dst, flow->dl_dst)) {
return;
}
memcpy(base->dl_src, flow->dl_src, ETH_ADDR_LEN);
memcpy(base->dl_dst, flow->dl_dst, ETH_ADDR_LEN);
memcpy(eth_key.eth_src, base->dl_src, ETH_ADDR_LEN);
memcpy(eth_key.eth_dst, base->dl_dst, ETH_ADDR_LEN);
commit_set_action(odp_actions, OVS_KEY_ATTR_ETHERNET,
&eth_key, sizeof(eth_key));
}
static void
commit_vlan_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
if (base->vlan_tci == flow->vlan_tci) {
return;
}
if (base->vlan_tci & htons(VLAN_CFI)) {
nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_VLAN);
}
if (flow->vlan_tci & htons(VLAN_CFI)) {
struct ovs_action_push_vlan vlan;
vlan.vlan_tpid = htons(ETH_TYPE_VLAN);
vlan.vlan_tci = flow->vlan_tci;
nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_VLAN,
&vlan, sizeof vlan);
}
base->vlan_tci = flow->vlan_tci;
}
static void
commit_set_nw_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
struct ovs_key_ipv4 ipv4_key;
if (base->dl_type != htons(ETH_TYPE_IP) ||
!base->nw_src || !base->nw_dst) {
return;
}
if (base->nw_src == flow->nw_src &&
base->nw_dst == flow->nw_dst &&
base->nw_tos == flow->nw_tos &&
base->nw_ttl == flow->nw_ttl &&
base->nw_frag == flow->nw_frag) {
return;
}
ipv4_key.ipv4_src = base->nw_src = flow->nw_src;
ipv4_key.ipv4_dst = base->nw_dst = flow->nw_dst;
ipv4_key.ipv4_tos = base->nw_tos = flow->nw_tos;
ipv4_key.ipv4_ttl = base->nw_ttl = flow->nw_ttl;
ipv4_key.ipv4_proto = base->nw_proto;
ipv4_key.ipv4_frag = (base->nw_frag == 0 ? OVS_FRAG_TYPE_NONE
: base->nw_frag == FLOW_NW_FRAG_ANY
? OVS_FRAG_TYPE_FIRST : OVS_FRAG_TYPE_LATER);
commit_set_action(odp_actions, OVS_KEY_ATTR_IPV4,
&ipv4_key, sizeof(ipv4_key));
}
static void
commit_set_port_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
if (!base->tp_src || !base->tp_dst) {
return;
}
if (base->tp_src == flow->tp_src &&
base->tp_dst == flow->tp_dst) {
return;
}
if (flow->nw_proto == IPPROTO_TCP) {
struct ovs_key_tcp port_key;
port_key.tcp_src = base->tp_src = flow->tp_src;
port_key.tcp_dst = base->tp_dst = flow->tp_dst;
commit_set_action(odp_actions, OVS_KEY_ATTR_TCP,
&port_key, sizeof(port_key));
} else if (flow->nw_proto == IPPROTO_UDP) {
struct ovs_key_udp port_key;
port_key.udp_src = base->tp_src = flow->tp_src;
port_key.udp_dst = base->tp_dst = flow->tp_dst;
commit_set_action(odp_actions, OVS_KEY_ATTR_UDP,
&port_key, sizeof(port_key));
}
}
static void
commit_set_priority_action(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
if (base->priority == flow->priority) {
return;
}
base->priority = flow->priority;
commit_set_action(odp_actions, OVS_KEY_ATTR_PRIORITY,
&base->priority, sizeof(base->priority));
}
/* If any of the flow key data that ODP actions can modify are different in
* 'base' and 'flow', appends ODP actions to 'odp_actions' that change the flow
* key from 'base' into 'flow', and then changes 'base' the same way. */
void
commit_odp_actions(const struct flow *flow, struct flow *base,
struct ofpbuf *odp_actions)
{
commit_set_tun_id_action(flow, base, odp_actions);
commit_set_ether_addr_action(flow, base, odp_actions);
commit_vlan_action(flow, base, odp_actions);
commit_set_nw_action(flow, base, odp_actions);
commit_set_port_action(flow, base, odp_actions);
commit_set_priority_action(flow, base, odp_actions);
}