This follows the pattern I see elsewhere for other "set" actions, but I am
uncertain about some parts:
* I am not sure that set_arp() is called in a context where there is
guaranteed to be a full Ethernet+IP ARP header present in the packet,
given megaflows.
* set_arp() as written here allows an arp_op >=0x100 to be set even
though flow_extract() only parses arp_op <0x100. This is probably
not right, but I'm not sure of the correct fix.
* The tree now has two (struct arp_eth_header *)skb_network_header(skb)
casts, perhaps I should add an arp_eth_hdr() helper.
Signed-off-by: Ben Pfaff <[email protected]>
---
datapath/actions.c | 24 ++++++++++++++++++++++++
datapath/datapath.c | 9 +++++++++
2 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/datapath/actions.c b/datapath/actions.c
index 0a2def6..d483283 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -360,6 +360,26 @@ static int set_tcp(struct sk_buff *skb, const struct
ovs_key_tcp *tcp_port_key)
return 0;
}
+static int set_arp(struct sk_buff *skb, const struct ovs_key_arp *arp_key)
+{
+ struct arp_eth_header *ah;
+ int err;
+
+ err = make_writable(skb, skb_network_offset(skb) +
+ sizeof(struct arp_eth_header));
+ if (unlikely(err))
+ return err;
+
+ ah = (struct arp_eth_header *)skb_network_header(skb);
+ ah->ar_op = arp_key->arp_op;
+ memcpy(ah->ar_sha, arp_key->arp_sha, ETH_ALEN);
+ memcpy(ah->ar_sip, &arp_key->arp_sip, 4);
+ memcpy(ah->ar_tha, arp_key->arp_tha, ETH_ALEN);
+ memcpy(ah->ar_tip, &arp_key->arp_tip, 4);
+
+ return 0;
+}
+
static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
{
struct vport *vport;
@@ -469,6 +489,10 @@ static int execute_set_action(struct sk_buff *skb,
case OVS_KEY_ATTR_UDP:
err = set_udp(skb, nla_data(nested_attr));
break;
+
+ case OVS_KEY_ATTR_ARP:
+ err = set_arp(skb, nla_data(nested_attr));
+ break;
}
return err;
diff --git a/datapath/datapath.c b/datapath/datapath.c
index 2f02f71..0786379 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -726,6 +726,15 @@ static int validate_set(const struct nlattr *a,
return validate_tp_port(flow_key);
+ case OVS_KEY_ATTR_ARP:
+ if (flow_key->eth.type != htons(ETH_P_ARP))
+ return -EINVAL;
+
+ if (!flow_key->ip.proto)
+ return -EINVAL;
+
+ return 0;
+
default:
return -EINVAL;
}
--
1.7.2.5
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev