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 <b...@nicira.com> --- 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 dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev