Until now, compose_arp() has only been able to compose ARP requests.  This
extends it to composing general ARP packets, in particular replies.
An upcoming commit will make use of this capability.

Signed-off-by: Ben Pfaff <b...@nicira.com>
---
 lib/packets.c                | 28 ++++++++++++++++++----------
 lib/packets.h                | 11 ++++++++---
 ofproto/ofproto-dpif-xlate.c |  3 ++-
 3 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/lib/packets.c b/lib/packets.c
index 965754f..d04fffc 100644
--- a/lib/packets.c
+++ b/lib/packets.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -1012,9 +1012,16 @@ packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags)
 #define ARP_PACKET_SIZE  (2 + ETH_HEADER_LEN + VLAN_HEADER_LEN + \
                           ARP_ETH_HEADER_LEN)
 
+/* Clears 'b' and replaces its contents by an ARP frame with the specified
+ * 'arp_op', 'arp_sha', 'arp_tha', 'arp_spa', and 'arp_tpa'.  The outer
+ * Ethernet frame is initialized with Ethernet source 'arp_sha' and destination
+ * 'arp_tha', except that destination ff:ff:ff:ff:ff:ff is used instead if
+ * 'broadcast' is true. */
 void
-compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
-            ovs_be32 ip_src, ovs_be32 ip_dst)
+compose_arp(struct dp_packet *b, uint16_t arp_op,
+            const uint8_t arp_sha[ETH_ADDR_LEN],
+            const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
+            ovs_be32 arp_spa, ovs_be32 arp_tpa)
 {
     struct eth_header *eth;
     struct arp_eth_header *arp;
@@ -1024,8 +1031,9 @@ compose_arp(struct dp_packet *b, const uint8_t 
eth_src[ETH_ADDR_LEN],
     dp_packet_reserve(b, 2 + VLAN_HEADER_LEN);
 
     eth = dp_packet_put_uninit(b, sizeof *eth);
-    memcpy(eth->eth_dst, eth_addr_broadcast, ETH_ADDR_LEN);
-    memcpy(eth->eth_src, eth_src, ETH_ADDR_LEN);
+    memcpy(eth->eth_dst, broadcast ? eth_addr_broadcast : arp_tha,
+           ETH_ADDR_LEN);
+    memcpy(eth->eth_src, arp_sha, ETH_ADDR_LEN);
     eth->eth_type = htons(ETH_TYPE_ARP);
 
     arp = dp_packet_put_uninit(b, sizeof *arp);
@@ -1033,12 +1041,12 @@ compose_arp(struct dp_packet *b, const uint8_t 
eth_src[ETH_ADDR_LEN],
     arp->ar_pro = htons(ARP_PRO_IP);
     arp->ar_hln = sizeof arp->ar_sha;
     arp->ar_pln = sizeof arp->ar_spa;
-    arp->ar_op = htons(ARP_OP_REQUEST);
-    memcpy(arp->ar_sha, eth_src, ETH_ADDR_LEN);
-    memset(arp->ar_tha, 0, ETH_ADDR_LEN);
+    arp->ar_op = htons(arp_op);
+    memcpy(arp->ar_sha, arp_sha, ETH_ADDR_LEN);
+    memcpy(arp->ar_tha, arp_tha, ETH_ADDR_LEN);
 
-    put_16aligned_be32(&arp->ar_spa, ip_src);
-    put_16aligned_be32(&arp->ar_tpa, ip_dst);
+    put_16aligned_be32(&arp->ar_spa, arp_spa);
+    put_16aligned_be32(&arp->ar_tpa, arp_tpa);
 
     dp_packet_reset_offsets(b);
     dp_packet_set_l3(b, arp);
diff --git a/lib/packets.h b/lib/packets.h
index e22267e..699a953 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -77,6 +77,9 @@ bool dpid_from_string(const char *s, uint64_t *dpidp);
 static const uint8_t eth_addr_broadcast[ETH_ADDR_LEN] OVS_UNUSED
     = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 
+static const uint8_t eth_addr_zero[ETH_ADDR_LEN] OVS_UNUSED
+    = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
 static const uint8_t eth_addr_stp[ETH_ADDR_LEN] OVS_UNUSED
     = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x00 };
 
@@ -811,8 +814,10 @@ void packet_set_nd(struct dp_packet *, const ovs_be32 
target[4],
 
 void packet_format_tcp_flags(struct ds *, uint16_t);
 const char *packet_tcp_flag_to_string(uint32_t flag);
-void compose_arp(struct dp_packet *b, const uint8_t eth_src[ETH_ADDR_LEN],
-                 ovs_be32 ip_src, ovs_be32 ip_dst);
+void compose_arp(struct dp_packet *, uint16_t arp_op,
+                 const uint8_t arp_sha[ETH_ADDR_LEN],
+                 const uint8_t arp_tha[ETH_ADDR_LEN], bool broadcast,
+                 ovs_be32 arp_spa, ovs_be32 arp_tpa);
 uint32_t packet_csum_pseudoheader(const struct ip_header *);
 
 #endif /* packets.h */
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
index 337d6f8..ef9312b 100644
--- a/ofproto/ofproto-dpif-xlate.c
+++ b/ofproto/ofproto-dpif-xlate.c
@@ -2659,7 +2659,8 @@ tnl_send_arp_request(const struct xport *out_dev, const 
uint8_t eth_src[ETH_ADDR
     struct dp_packet packet;
 
     dp_packet_init(&packet, 0);
-    compose_arp(&packet, eth_src, ip_src, ip_dst);
+    compose_arp(&packet, ARP_OP_REQUEST,
+                eth_src, eth_addr_zero, true, ip_src, ip_dst);
 
     xlate_flood_packet(xbridge, &packet);
     dp_packet_uninit(&packet);
-- 
2.1.3

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to