diff options
author | Andy Zhou <azhou@nicira.com> | 2014-09-15 22:37:25 -0400 |
---|---|---|
committer | Pravin B Shelar <pshelar@nicira.com> | 2014-09-16 02:28:14 -0400 |
commit | 971427f353f3c42c8dcef62e7124440df68eb809 (patch) | |
tree | 7eed9ed50fe70cfc82ce33e12a13147ad0de580c /net/openvswitch/flow_netlink.c | |
parent | 32ae87ff795781b7ceffc44b7c694c1bb206a266 (diff) |
openvswitch: Add recirc and hash action.
Recirc action allows a packet to reenter openvswitch processing.
currently openvswitch lookup flow for packet received and execute
set of actions on that packet, with help of recirc action we can
process/modify the packet and recirculate it back in openvswitch
for another pass.
OVS hash action calculates 5-tupple hash and set hash in flow-key
hash. This can be used along with recirculation for distributing
packets among different ports for bond devices.
For example:
OVS bonding can use following actions:
Match on: bond flow; Action: hash, recirc(id)
Match on: recirc-id == id and hash lower bits == a;
Action: output port_bond_a
Signed-off-by: Andy Zhou <azhou@nicira.com>
Acked-by: Jesse Gross <jesse@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Diffstat (limited to 'net/openvswitch/flow_netlink.c')
-rw-r--r-- | net/openvswitch/flow_netlink.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 630b320fbf3e..f4c8daa73965 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2007-2013 Nicira, Inc. | 2 | * Copyright (c) 2007-2014 Nicira, Inc. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or | 4 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of version 2 of the GNU General Public | 5 | * modify it under the terms of version 2 of the GNU General Public |
@@ -251,6 +251,8 @@ static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = { | |||
251 | [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6), | 251 | [OVS_KEY_ATTR_ICMPV6] = sizeof(struct ovs_key_icmpv6), |
252 | [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp), | 252 | [OVS_KEY_ATTR_ARP] = sizeof(struct ovs_key_arp), |
253 | [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd), | 253 | [OVS_KEY_ATTR_ND] = sizeof(struct ovs_key_nd), |
254 | [OVS_KEY_ATTR_RECIRC_ID] = sizeof(u32), | ||
255 | [OVS_KEY_ATTR_DP_HASH] = sizeof(u32), | ||
254 | [OVS_KEY_ATTR_TUNNEL] = -1, | 256 | [OVS_KEY_ATTR_TUNNEL] = -1, |
255 | }; | 257 | }; |
256 | 258 | ||
@@ -454,6 +456,20 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb, | |||
454 | static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs, | 456 | static int metadata_from_nlattrs(struct sw_flow_match *match, u64 *attrs, |
455 | const struct nlattr **a, bool is_mask) | 457 | const struct nlattr **a, bool is_mask) |
456 | { | 458 | { |
459 | if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) { | ||
460 | u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]); | ||
461 | |||
462 | SW_FLOW_KEY_PUT(match, ovs_flow_hash, hash_val, is_mask); | ||
463 | *attrs &= ~(1 << OVS_KEY_ATTR_DP_HASH); | ||
464 | } | ||
465 | |||
466 | if (*attrs & (1 << OVS_KEY_ATTR_RECIRC_ID)) { | ||
467 | u32 recirc_id = nla_get_u32(a[OVS_KEY_ATTR_RECIRC_ID]); | ||
468 | |||
469 | SW_FLOW_KEY_PUT(match, recirc_id, recirc_id, is_mask); | ||
470 | *attrs &= ~(1 << OVS_KEY_ATTR_RECIRC_ID); | ||
471 | } | ||
472 | |||
457 | if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) { | 473 | if (*attrs & (1 << OVS_KEY_ATTR_PRIORITY)) { |
458 | SW_FLOW_KEY_PUT(match, phy.priority, | 474 | SW_FLOW_KEY_PUT(match, phy.priority, |
459 | nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask); | 475 | nla_get_u32(a[OVS_KEY_ATTR_PRIORITY]), is_mask); |
@@ -873,6 +889,12 @@ int ovs_nla_put_flow(const struct sw_flow_key *swkey, | |||
873 | struct nlattr *nla, *encap; | 889 | struct nlattr *nla, *encap; |
874 | bool is_mask = (swkey != output); | 890 | bool is_mask = (swkey != output); |
875 | 891 | ||
892 | if (nla_put_u32(skb, OVS_KEY_ATTR_RECIRC_ID, output->recirc_id)) | ||
893 | goto nla_put_failure; | ||
894 | |||
895 | if (nla_put_u32(skb, OVS_KEY_ATTR_DP_HASH, output->ovs_flow_hash)) | ||
896 | goto nla_put_failure; | ||
897 | |||
876 | if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority)) | 898 | if (nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, output->phy.priority)) |
877 | goto nla_put_failure; | 899 | goto nla_put_failure; |
878 | 900 | ||
@@ -1401,11 +1423,13 @@ int ovs_nla_copy_actions(const struct nlattr *attr, | |||
1401 | /* Expected argument lengths, (u32)-1 for variable length. */ | 1423 | /* Expected argument lengths, (u32)-1 for variable length. */ |
1402 | static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = { | 1424 | static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = { |
1403 | [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32), | 1425 | [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32), |
1426 | [OVS_ACTION_ATTR_RECIRC] = sizeof(u32), | ||
1404 | [OVS_ACTION_ATTR_USERSPACE] = (u32)-1, | 1427 | [OVS_ACTION_ATTR_USERSPACE] = (u32)-1, |
1405 | [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan), | 1428 | [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan), |
1406 | [OVS_ACTION_ATTR_POP_VLAN] = 0, | 1429 | [OVS_ACTION_ATTR_POP_VLAN] = 0, |
1407 | [OVS_ACTION_ATTR_SET] = (u32)-1, | 1430 | [OVS_ACTION_ATTR_SET] = (u32)-1, |
1408 | [OVS_ACTION_ATTR_SAMPLE] = (u32)-1 | 1431 | [OVS_ACTION_ATTR_SAMPLE] = (u32)-1, |
1432 | [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash) | ||
1409 | }; | 1433 | }; |
1410 | const struct ovs_action_push_vlan *vlan; | 1434 | const struct ovs_action_push_vlan *vlan; |
1411 | int type = nla_type(a); | 1435 | int type = nla_type(a); |
@@ -1432,6 +1456,18 @@ int ovs_nla_copy_actions(const struct nlattr *attr, | |||
1432 | return -EINVAL; | 1456 | return -EINVAL; |
1433 | break; | 1457 | break; |
1434 | 1458 | ||
1459 | case OVS_ACTION_ATTR_HASH: { | ||
1460 | const struct ovs_action_hash *act_hash = nla_data(a); | ||
1461 | |||
1462 | switch (act_hash->hash_alg) { | ||
1463 | case OVS_HASH_ALG_L4: | ||
1464 | break; | ||
1465 | default: | ||
1466 | return -EINVAL; | ||
1467 | } | ||
1468 | |||
1469 | break; | ||
1470 | } | ||
1435 | 1471 | ||
1436 | case OVS_ACTION_ATTR_POP_VLAN: | 1472 | case OVS_ACTION_ATTR_POP_VLAN: |
1437 | break; | 1473 | break; |
@@ -1444,6 +1480,9 @@ int ovs_nla_copy_actions(const struct nlattr *attr, | |||
1444 | return -EINVAL; | 1480 | return -EINVAL; |
1445 | break; | 1481 | break; |
1446 | 1482 | ||
1483 | case OVS_ACTION_ATTR_RECIRC: | ||
1484 | break; | ||
1485 | |||
1447 | case OVS_ACTION_ATTR_SET: | 1486 | case OVS_ACTION_ATTR_SET: |
1448 | err = validate_set(a, key, sfa, &skip_copy); | 1487 | err = validate_set(a, key, sfa, &skip_copy); |
1449 | if (err) | 1488 | if (err) |