ovs-dpctl: Add mega flow support
[sliver-openvswitch.git] / lib / packets.h
index 24b51da..cc9ab3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <stdint.h>
 #include <string.h>
 #include "compiler.h"
+#include "flow.h"
 #include "openvswitch/types.h"
 #include "random.h"
 #include "util.h"
 
 struct ofpbuf;
 struct ds;
-struct flow;
 
 bool dpid_from_string(const char *s, uint64_t *dpidp);
 
@@ -140,6 +140,10 @@ void compose_rarp(struct ofpbuf *, const uint8_t eth_src[ETH_ADDR_LEN]);
 void eth_push_vlan(struct ofpbuf *, ovs_be16 tci);
 void eth_pop_vlan(struct ofpbuf *);
 
+uint16_t eth_mpls_depth(const struct ofpbuf *packet);
+
+void set_ethertype(struct ofpbuf *packet, ovs_be16 eth_type);
+
 const char *eth_from_hex(const char *hex, struct ofpbuf **packetp);
 void eth_format_masked(const uint8_t eth[ETH_ADDR_LEN],
                        const uint8_t mask[ETH_ADDR_LEN], struct ds *s);
@@ -147,6 +151,17 @@ void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
                      const uint8_t mask[ETH_ADDR_LEN],
                      uint8_t dst[ETH_ADDR_LEN]);
 
+void set_mpls_lse(struct ofpbuf *, ovs_be32 label);
+void push_mpls(struct ofpbuf *packet, ovs_be16 ethtype, ovs_be32 lse);
+void pop_mpls(struct ofpbuf *, ovs_be16 ethtype);
+
+void set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl);
+void set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc);
+void set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label);
+void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos);
+ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos,
+                             ovs_be32 label);
+
 /* Example:
  *
  * uint8_t mac[ETH_ADDR_LEN];
@@ -177,13 +192,21 @@ void eth_addr_bitand(const uint8_t src[ETH_ADDR_LEN],
 
 #define ETH_TYPE_IP            0x0800
 #define ETH_TYPE_ARP           0x0806
-#define ETH_TYPE_VLAN          0x8100
+#define ETH_TYPE_VLAN_8021Q    0x8100
+#define ETH_TYPE_VLAN          ETH_TYPE_VLAN_8021Q
+#define ETH_TYPE_VLAN_8021AD   0x88a8
 #define ETH_TYPE_IPV6          0x86dd
 #define ETH_TYPE_LACP          0x8809
 #define ETH_TYPE_RARP          0x8035
 #define ETH_TYPE_MPLS          0x8847
 #define ETH_TYPE_MPLS_MCAST    0x8848
 
+static inline bool eth_type_mpls(ovs_be16 eth_type)
+{
+    return eth_type == htons(ETH_TYPE_MPLS) ||
+        eth_type == htons(ETH_TYPE_MPLS_MCAST);
+}
+
 /* Minimum value for an Ethernet type.  Values below this are IEEE 802.2 frame
  * lengths. */
 #define ETH_TYPE_MIN           0x600
@@ -236,6 +259,7 @@ BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header));
 #define VLAN_PCP_SHIFT 13
 
 #define VLAN_CFI 0x1000
+#define VLAN_CFI_SHIFT 12
 
 /* Given the vlan_tci field from an 802.1Q header, in network byte order,
  * returns the VLAN ID in host byte order. */
@@ -253,6 +277,14 @@ vlan_tci_to_pcp(ovs_be16 vlan_tci)
     return (ntohs(vlan_tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT;
 }
 
+/* Given the vlan_tci field from an 802.1Q header, in network byte order,
+ * returns the Canonical Format Indicator (CFI). */
+static inline int
+vlan_tci_to_cfi(ovs_be16 vlan_tci)
+{
+    return (vlan_tci & htons(VLAN_CFI)) != 0;
+}
+
 #define VLAN_HEADER_LEN 4
 struct vlan_header {
     ovs_be16 vlan_tci;          /* Lowest 12 bits are VLAN ID. */
@@ -270,16 +302,72 @@ struct vlan_eth_header {
 } __attribute__((packed));
 BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header));
 
-/* The "(void) (ip)[0]" below has no effect on the value, since it's the first
- * argument of a comma expression, but it makes sure that 'ip' is a pointer.
- * This is useful since a common mistake is to pass an integer instead of a
- * pointer to IP_ARGS. */
-#define IP_FMT "%"PRIu8".%"PRIu8".%"PRIu8".%"PRIu8
+/* MPLS related definitions */
+#define MPLS_TTL_MASK       0x000000ff
+#define MPLS_TTL_SHIFT      0
+
+#define MPLS_BOS_MASK       0x00000100
+#define MPLS_BOS_SHIFT      8
+
+#define MPLS_TC_MASK        0x00000e00
+#define MPLS_TC_SHIFT       9
+
+#define MPLS_LABEL_MASK     0xfffff000
+#define MPLS_LABEL_SHIFT    12
+
+#define MPLS_HLEN           4
+
+struct mpls_hdr {
+    ovs_be32 mpls_lse;
+};
+BUILD_ASSERT_DECL(MPLS_HLEN == sizeof(struct mpls_hdr));
+
+/* Given a mpls label stack entry in network byte order
+ * return mpls label in host byte order */
+static inline uint32_t
+mpls_lse_to_label(ovs_be32 mpls_lse)
+{
+    return (ntohl(mpls_lse) & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT;
+}
+
+/* Given a mpls label stack entry in network byte order
+ * return mpls tc */
+static inline uint8_t
+mpls_lse_to_tc(ovs_be32 mpls_lse)
+{
+    return (ntohl(mpls_lse) & MPLS_TC_MASK) >> MPLS_TC_SHIFT;
+}
+
+/* Given a mpls label stack entry in network byte order
+ * return mpls ttl */
+static inline uint8_t
+mpls_lse_to_ttl(ovs_be32 mpls_lse)
+{
+    return (ntohl(mpls_lse) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT;
+}
+
+/* Set TTL in mpls lse. */
+static inline void
+flow_set_mpls_lse_ttl(ovs_be32 *mpls_lse, uint8_t ttl)
+{
+    *mpls_lse &= ~htonl(MPLS_TTL_MASK);
+    *mpls_lse |= htonl(ttl << MPLS_TTL_SHIFT);
+}
+
+/* Given a mpls label stack entry in network byte order
+ * return mpls BoS bit  */
+static inline uint8_t
+mpls_lse_to_bos(ovs_be32 mpls_lse)
+{
+    return (mpls_lse & htonl(MPLS_BOS_MASK)) != 0;
+}
+
+#define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32
 #define IP_ARGS(ip)                             \
-        ((void) (ip)[0], ((uint8_t *) ip)[0]),  \
-        ((uint8_t *) ip)[1],                    \
-        ((uint8_t *) ip)[2],                    \
-        ((uint8_t *) ip)[3]
+    ntohl(ip) >> 24,                            \
+    (ntohl(ip) >> 16) & 0xff,                   \
+    (ntohl(ip) >> 8) & 0xff,                    \
+    ntohl(ip) & 0xff
 
 /* Example:
  *
@@ -470,6 +558,17 @@ static inline bool ipv6_mask_is_exact(const struct in6_addr *mask) {
     return ipv6_addr_equals(mask, &in6addr_exact);
 }
 
+static inline bool dl_type_is_ip_any(ovs_be16 dl_type)
+{
+    return dl_type == htons(ETH_TYPE_IP)
+        || dl_type == htons(ETH_TYPE_IPV6);
+}
+
+static inline bool is_ip_any(const struct flow *flow)
+{
+    return dl_type_is_ip_any(flow->dl_type);
+}
+
 void format_ipv6_addr(char *addr_str, const struct in6_addr *addr);
 void print_ipv6_addr(struct ds *string, const struct in6_addr *addr);
 void print_ipv6_masked(struct ds *string, const struct in6_addr *addr,
@@ -488,6 +587,9 @@ void *snap_compose(struct ofpbuf *, const uint8_t eth_dst[ETH_ADDR_LEN],
                    unsigned int oui, uint16_t snap_type, size_t size);
 void packet_set_ipv4(struct ofpbuf *, ovs_be32 src, ovs_be32 dst, uint8_t tos,
                      uint8_t ttl);
+void packet_set_ipv6(struct ofpbuf *, uint8_t proto, const ovs_be32 src[4],
+                     const ovs_be32 dst[4], uint8_t tc,
+                     ovs_be32 fl, uint8_t hlmit);
 void packet_set_tcp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);
 void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst);