/*
- * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+ * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* This sequence number should be incremented whenever anything involving flows
* or the wildcarding of flows changes. This will cause build assertion
* failures in places which likely need to be updated. */
-#define FLOW_WC_SEQ 33
+#define FLOW_WC_SEQ 35
/* Number of Open vSwitch extension 32-bit registers. */
#define FLOW_N_REGS 8
BUILD_ASSERT_DECL(FLOW_NW_FRAG_ANY == NX_IP_FRAG_ANY);
BUILD_ASSERT_DECL(FLOW_NW_FRAG_LATER == NX_IP_FRAG_LATER);
-/* Some flags are exposed through OpenFlow while others are used only
- * internally. */
-
-/* Public flags */
-#define FLOW_TNL_F_OAM (1 << 0)
-
-#define FLOW_TNL_PUB_F_MASK ((1 << 1) - 1)
BUILD_ASSERT_DECL(FLOW_TNL_F_OAM == NX_TUN_FLAG_OAM);
-/* Private flags */
-#define FLOW_TNL_F_DONT_FRAGMENT (1 << 1)
-#define FLOW_TNL_F_CSUM (1 << 2)
-#define FLOW_TNL_F_KEY (1 << 3)
-
-#define FLOW_TNL_F_MASK ((1 << 4) - 1)
-
-/* Purely internal to OVS userspace. These flags should never be exposed to
- * the outside world and so aren't included in the flags mask. */
-
-/* Tunnel information is in userspace datapath format. */
-#define FLOW_TNL_F_UDPIF (1 << 4)
-
const char *flow_tun_flag_to_string(uint32_t flags);
/* Maximum number of supported MPLS labels. */
* computation is opaque to the user space. */
union flow_in_port in_port; /* Input port.*/
uint32_t recirc_id; /* Must be exact match. */
+ uint16_t ct_state; /* Connection tracking state. */
+ uint16_t ct_zone; /* Connection tracking zone. */
+ uint32_t ct_mark; /* Connection mark.*/
+ uint8_t pad1[4]; /* Pad to 64 bits. */
+ ovs_u128 ct_label; /* Connection label. */
uint32_t conj_id; /* Conjunction ID. */
ofp_port_t actset_output; /* Output port in action set. */
- uint8_t pad1[6]; /* Pad to 64 bits. */
+ uint8_t pad2[2]; /* Pad to 64 bits. */
/* L2, Order the same as in the Ethernet header! (64-bit aligned) */
- uint8_t dl_dst[ETH_ADDR_LEN]; /* Ethernet destination address. */
- uint8_t dl_src[ETH_ADDR_LEN]; /* Ethernet source address. */
+ struct eth_addr dl_dst; /* Ethernet destination address. */
+ struct eth_addr dl_src; /* Ethernet source address. */
ovs_be16 dl_type; /* Ethernet frame type. */
ovs_be16 vlan_tci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */
ovs_be32 mpls_lse[ROUND_UP(FLOW_MAX_MPLS_LABELS, 2)]; /* MPLS label stack
uint8_t nw_ttl; /* IP TTL/Hop Limit. */
uint8_t nw_proto; /* IP protocol or low 8 bits of ARP opcode. */
struct in6_addr nd_target; /* IPv6 neighbor discovery (ND) target. */
- uint8_t arp_sha[ETH_ADDR_LEN]; /* ARP/ND source hardware address. */
- uint8_t arp_tha[ETH_ADDR_LEN]; /* ARP/ND target hardware address. */
+ struct eth_addr arp_sha; /* ARP/ND source hardware address. */
+ struct eth_addr arp_tha; /* ARP/ND target hardware address. */
ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */
- ovs_be16 pad2; /* Pad to 64 bits. */
+ ovs_be16 pad3; /* Pad to 64 bits. */
/* L4 (64-bit aligned) */
- ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */
- ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port. */
+ ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */
+ ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port/ICMP code. */
ovs_be32 igmp_group_ip4; /* IGMP group IPv4 address.
* Keep last for BUILD_ASSERT_DECL below. */
};
/* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */
BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t)
- == sizeof(struct flow_tnl) + 192
- && FLOW_WC_SEQ == 33);
+ == sizeof(struct flow_tnl) + 216
+ && FLOW_WC_SEQ == 35);
/* Incremental points at which flow classification may be performed in
* segments.
void flow_unwildcard_tp_ports(const struct flow *, struct flow_wildcards *);
void flow_get_metadata(const struct flow *, struct match *flow_metadata);
+const char *ct_state_to_string(uint32_t state);
char *flow_to_string(const struct flow *);
void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t),
uint32_t flags, char del);
static inline size_t
flow_hash(const struct flow *flow, uint32_t basis)
{
- return hash_words64((const uint64_t *)flow,
- sizeof *flow / sizeof(uint64_t), basis);
+ return hash_bytes64((const uint64_t *)flow, sizeof *flow, basis);
}
static inline uint16_t
#define WC_MASK_FIELD(WC, FIELD) \
memset(&(WC)->masks.FIELD, 0xff, sizeof (WC)->masks.FIELD)
+#define WC_MASK_FIELD_MASK(WC, FIELD, MASK) \
+ ((WC)->masks.FIELD |= (MASK))
#define WC_UNMASK_FIELD(WC, FIELD) \
memset(&(WC)->masks.FIELD, 0, sizeof (WC)->masks.FIELD)
if (fm->bits[unit] & (n_bits_mask << idx)) {
return true;
}
- if (idx + n_bits > MAP_T_BITS) {
+ /* The seemingly unnecessary bounds check on 'unit' is a workaround for a
+ * false-positive array out of bounds error by GCC 4.9. */
+ if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) {
/* Check the remaining bits from the next unit. */
return fm->bits[unit + 1] & (n_bits_mask >> (MAP_T_BITS - idx));
}
idx %= MAP_T_BITS;
fm->bits[unit] |= n_bits_mask << idx;
- if (idx + n_bits > MAP_T_BITS) {
+ /* The seemingly unnecessary bounds check on 'unit' is a workaround for a
+ * false-positive array out of bounds error by GCC 4.9. */
+ if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) {
/* 'MAP_T_BITS - idx' bits were set on 'unit', set the remaining
* bits from the next unit. */
fm->bits[unit + 1] |= n_bits_mask >> (MAP_T_BITS - idx);
idx %= MAP_T_BITS;
fm->bits[unit] &= ~(n_bits_mask << idx);
- if (idx + n_bits > MAP_T_BITS) {
+ /* The seemingly unnecessary bounds check on 'unit' is a workaround for a
+ * false-positive array out of bounds error by GCC 4.9. */
+ if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) {
/* 'MAP_T_BITS - idx' bits were cleared on 'unit', clear the
* remaining bits from the next unit. */
fm->bits[unit + 1] &= ~(n_bits_mask >> (MAP_T_BITS - idx));
/* OR the bits in the flowmaps. */
static inline struct flowmap
-flowmap_or(struct flowmap a, const struct flowmap b)
+flowmap_or(struct flowmap a, struct flowmap b)
{
struct flowmap map;
size_t unit;
/* AND the bits in the flowmaps. */
static inline struct flowmap
-flowmap_and(struct flowmap a, const struct flowmap b)
+flowmap_and(struct flowmap a, struct flowmap b)
{
struct flowmap map;
size_t unit;
}
static inline bool
-flowmap_is_empty(const struct flowmap fm)
+flowmap_is_empty(struct flowmap fm)
{
map_t map;
[FLOW_U64_OFFREM(FIELD) / sizeof(TYPE)] \
: 0)
+#define MINIFLOW_GET_U128(FLOW, FIELD) \
+ (ovs_u128) { .u64 = { \
+ (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD)) ? \
+ *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD)) : 0), \
+ (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD) + 1) ? \
+ *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD) + 1) : 0) } }
+
#define MINIFLOW_GET_U8(FLOW, FIELD) \
MINIFLOW_GET_TYPE(FLOW, uint8_t, FIELD)
#define MINIFLOW_GET_U16(FLOW, FIELD) \
{
md->recirc_id = flow->recirc_id;
md->dp_hash = flow->dp_hash;
- md->tunnel = flow->tunnel;
+ flow_tnl_copy__(&md->tunnel, &flow->tunnel);
md->skb_priority = flow->skb_priority;
md->pkt_mark = flow->pkt_mark;
md->in_port = flow->in_port;
+ md->ct_state = flow->ct_state;
+ md->ct_zone = flow->ct_zone;
+ md->ct_mark = flow->ct_mark;
+ md->ct_label = flow->ct_label;
}
static inline bool is_ip_any(const struct flow *flow)