Merge remote-tracking branch 'ovs-dev/master'
[sliver-openvswitch.git] / lib / packets.c
index 4f57d16..b95e1e0 100644 (file)
@@ -27,6 +27,7 @@
 #include "hmap.h"
 #include "dynamic-string.h"
 #include "ofpbuf.h"
+#include "ovs-thread.h"
 
 const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT;
 
@@ -54,27 +55,27 @@ eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN])
 {
     struct eth_addr_node {
         struct hmap_node hmap_node;
-        uint64_t ea64;
+        const uint64_t ea64;
     };
 
     static struct eth_addr_node nodes[] = {
         /* STP, IEEE pause frames, and other reserved protocols. */
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000000ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000001ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000002ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000003ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000004ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000005ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000006ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000007ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000008ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c2000009ULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000aULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000bULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000cULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000dULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000eULL },
-        { HMAP_NODE_NULL_INITIALIZER, 0x0108c200000fULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000000ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000001ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000002ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000003ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000004ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000005ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000006ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000007ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000008ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c2000009ULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000aULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000bULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000cULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000dULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000eULL },
+        { HMAP_NODE_NULL_INITIALIZER, 0x0180c200000fULL },
 
         /* Extreme protocols. */
         { HMAP_NODE_NULL_INITIALIZER, 0x00e02b000000ULL }, /* EDP. */
@@ -100,15 +101,18 @@ eth_addr_is_reserved(const uint8_t ea[ETH_ADDR_LEN])
         { HMAP_NODE_NULL_INITIALIZER, 0x01000cccccc7ULL },
     };
 
-    static struct hmap addrs = HMAP_INITIALIZER(&addrs);
+    static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
     struct eth_addr_node *node;
+    static struct hmap addrs;
     uint64_t ea64;
 
-    if (hmap_is_empty(&addrs)) {
+    if (ovsthread_once_start(&once)) {
+        hmap_init(&addrs);
         for (node = nodes; node < &nodes[ARRAY_SIZE(nodes)]; node++) {
             hmap_insert(&addrs, &node->hmap_node,
                         hash_2words(node->ea64, node->ea64 >> 32));
         }
+        ovsthread_once_done(&once);
     }
 
     ea64 = eth_addr_to_uint64(ea);
@@ -246,7 +250,8 @@ set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type)
 
     if (eh->eth_type == htons(ETH_TYPE_VLAN)) {
         ovs_be16 *p;
-        p = (ovs_be16 *)((char *)(packet->l2_5 ? packet->l2_5 : packet->l3) - 2);
+        p = ALIGNED_CAST(ovs_be16 *,
+                (char *)(packet->l2_5 ? packet->l2_5 : packet->l3) - 2);
         *p = eth_type;
     } else {
         eh->eth_type = eth_type;
@@ -259,7 +264,7 @@ static bool is_mpls(struct ofpbuf *packet)
 }
 
 /* Set time to live (TTL) of an MPLS label stack entry (LSE). */
-static void
+void
 set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl)
 {
     *lse &= ~htonl(MPLS_TTL_MASK);
@@ -373,10 +378,9 @@ pop_mpls(struct ofpbuf *packet, ovs_be16 ethtype)
         size_t len;
         mh = packet->l2_5;
         len = (char*)packet->l2_5 - (char*)packet->l2;
-        /* If bottom of the stack set ethertype. */
+        set_ethertype(packet, ethtype);
         if (mh->mpls_lse & htonl(MPLS_BOS_MASK)) {
             packet->l2_5 = NULL;
-            set_ethertype(packet, ethtype);
         } else {
             packet->l2_5 = (char*)packet->l2_5 + MPLS_HLEN;
         }
@@ -667,7 +671,7 @@ packet_rh_present(struct ofpbuf *packet)
     if (remaining < sizeof *nh) {
         return false;
     }
-    nh = (struct ip6_hdr *)data;
+    nh = ALIGNED_CAST(struct ip6_hdr *, data);
     data += sizeof *nh;
     remaining -= sizeof *nh;
     nexthdr = nh->ip6_nxt;
@@ -703,7 +707,8 @@ packet_rh_present(struct ofpbuf *packet)
             nexthdr = ext_hdr->ip6e_nxt;
             len = (ext_hdr->ip6e_len + 2) * 4;
         } else if (nexthdr == IPPROTO_FRAGMENT) {
-            const struct ip6_frag *frag_hdr = (struct ip6_frag *)data;
+            const struct ip6_frag *frag_hdr = ALIGNED_CAST(struct ip6_frag *,
+                                                           data);
 
             nexthdr = frag_hdr->ip6f_nxt;
             len = sizeof *frag_hdr;
@@ -887,7 +892,8 @@ packet_set_udp_port(struct ofpbuf *packet, ovs_be16 src, ovs_be16 dst)
 uint8_t
 packet_get_tcp_flags(const struct ofpbuf *packet, const struct flow *flow)
 {
-    if (is_ip_any(flow) && flow->nw_proto == IPPROTO_TCP && packet->l7) {
+    if (dl_type_is_ip_any(flow->dl_type) &&
+        flow->nw_proto == IPPROTO_TCP && packet->l7) {
         const struct tcp_header *tcp = packet->l4;
         return TCP_FLAGS(tcp->tcp_ctl);
     } else {