mcast-snooping: Add Multicast Listener Discovery support
[cascardo/ovs.git] / lib / packets.c
index 965754f..b37abde 100644 (file)
@@ -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.
@@ -34,6 +34,7 @@
 #include "unaligned.h"
 
 const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
+const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT;
 
 /* Parses 's' as a 16-digit hexadecimal number representing a datapath ID.  On
  * success stores the dpid into '*dpidp' and returns true, on failure stores 0
@@ -437,6 +438,17 @@ print_ipv6_addr(struct ds *string, const struct in6_addr *addr)
     string->length += strlen(dst);
 }
 
+void
+print_ipv6_mapped(struct ds *s, const struct in6_addr *addr)
+{
+    if (IN6_IS_ADDR_V4MAPPED(addr)) {
+        ds_put_format(s, IP_FMT, addr->s6_addr[12], addr->s6_addr[13],
+                                 addr->s6_addr[14], addr->s6_addr[15]);
+    } else {
+        print_ipv6_addr(s, addr);
+    }
+}
+
 void
 print_ipv6_masked(struct ds *s, const struct in6_addr *addr,
                   const struct in6_addr *mask)
@@ -1012,9 +1024,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 +1043,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 +1053,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);