* away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are
* defined as macros. */
-#if (FLOW_WC_SEQ != 41)
+#if (FLOW_WC_SEQ != 42)
#define MINIFLOW_ASSERT(X) ovs_assert(X)
BUILD_MESSAGE("FLOW_WC_SEQ changed: miniflow_extract() will have runtime "
"assertions enabled. Consider updating FLOW_WC_SEQ after "
{
const ovs_be16 *eth_type;
- memset(vlan_hdrs, 0, sizeof(union flow_vlan_hdr) * FLOW_MAX_VLAN_HEADERS);
data_pull(datap, sizep, ETH_ADDR_LEN * 2);
eth_type = *datap;
break;
}
+ memset(vlan_hdrs + n, 0, sizeof(union flow_vlan_hdr));
const ovs_16aligned_be32 *qp = data_pull(datap, sizep, sizeof *qp);
vlan_hdrs[n].qtag = get_16aligned_be32(qp);
vlan_hdrs[n].tci |= htons(VLAN_CFI);
* and 'arp_buf[]' are filled in. If the packet is not an ND packet, 'false'
* is returned and no values are filled in on '*nd_target' or 'arp_buf[]'. */
static inline bool
-parse_icmpv6(const void **datap, size_t *sizep, const struct icmp6_hdr *icmp,
- uint32_t *rso_flags, const struct in6_addr **nd_target,
+parse_icmpv6(const void **datap, size_t *sizep,
+ const struct icmp6_data_header *icmp6,
+ ovs_be32 *rso_flags, const struct in6_addr **nd_target,
struct eth_addr arp_buf[2], uint8_t *opt_type)
{
- const uint32_t *reserved;
- if (icmp->icmp6_code != 0 ||
- (icmp->icmp6_type != ND_NEIGHBOR_SOLICIT &&
- icmp->icmp6_type != ND_NEIGHBOR_ADVERT)) {
+ if (icmp6->icmp6_base.icmp6_code != 0 ||
+ (icmp6->icmp6_base.icmp6_type != ND_NEIGHBOR_SOLICIT &&
+ icmp6->icmp6_base.icmp6_type != ND_NEIGHBOR_ADVERT)) {
return false;
}
arp_buf[1] = eth_addr_zero;
*opt_type = 0;
- reserved = data_try_pull(datap, sizep, sizeof(uint32_t));
- if (OVS_UNLIKELY(!reserved)) {
- /* Invalid ND packet. */
- return false;
- }
- *rso_flags = *reserved;
+ *rso_flags = get_16aligned_be32(icmp6->icmp6_data.be32);
*nd_target = data_try_pull(datap, sizep, sizeof **nd_target);
if (OVS_UNLIKELY(!*nd_target)) {
return false;
}
/* Jumbo Payload option not supported yet. */
- if (OVS_UNLIKELY(size - plen > UINT8_MAX)) {
+ if (OVS_UNLIKELY(size - (plen + IPV6_HEADER_LEN) > UINT8_MAX)) {
return false;
}
miniflow_extract(struct dp_packet *packet, struct miniflow *dst)
{
/* Add code to this function (or its callees) to extract new fields. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
const struct pkt_metadata *md = &packet->md;
const void *data = dp_packet_data(packet);
miniflow_pad_to_64(mf, igmp_group_ip4);
}
} else if (OVS_LIKELY(nw_proto == IPPROTO_ICMPV6)) {
- if (OVS_LIKELY(size >= sizeof(struct icmp6_hdr))) {
+ if (OVS_LIKELY(size >= sizeof(struct icmp6_data_header))) {
const struct in6_addr *nd_target;
struct eth_addr arp_buf[2];
/* This will populate whether we received Option 1
* or Option 2. */
uint8_t opt_type;
/* This holds the ND Reserved field. */
- uint32_t rso_flags;
- const struct icmp6_hdr *icmp = data_pull(&data,
- &size,ICMP6_HEADER_LEN);
- if (parse_icmpv6(&data, &size, icmp,
+ ovs_be32 rso_flags;
+ const struct icmp6_data_header *icmp6;
+
+ icmp6 = data_pull(&data, &size, sizeof *icmp6);
+ if (parse_icmpv6(&data, &size, icmp6,
&rso_flags, &nd_target, arp_buf, &opt_type)) {
if (nd_target) {
miniflow_push_words(mf, nd_target, nd_target,
* This will zero out the tcp_flags & pad3 field. */
miniflow_pad_to_64(mf, arp_tha);
}
- miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type));
- miniflow_push_be16(mf, tp_dst, htons(icmp->icmp6_code));
+ miniflow_push_be16(mf, tp_src,
+ htons(icmp6->icmp6_base.icmp6_type));
+ miniflow_push_be16(mf, tp_dst,
+ htons(icmp6->icmp6_base.icmp6_code));
miniflow_pad_to_64(mf, tp_dst);
/* Fill ND reserved field. */
- miniflow_push_be32(mf, igmp_group_ip4, htonl(rso_flags));
+ miniflow_push_be32(mf, igmp_group_ip4, rso_flags);
miniflow_pad_to_64(mf, igmp_group_ip4);
} else {
/* ICMPv6 but not ND. */
- miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type));
- miniflow_push_be16(mf, tp_dst, htons(icmp->icmp6_code));
+ miniflow_push_be16(mf, tp_src,
+ htons(icmp6->icmp6_base.icmp6_type));
+ miniflow_push_be16(mf, tp_dst,
+ htons(icmp6->icmp6_base.icmp6_code));
miniflow_push_be16(mf, ct_tp_src, ct_tp_src);
miniflow_push_be16(mf, ct_tp_dst, ct_tp_dst);
}
dst->map = mf.map;
}
-ovs_be16
-parse_dl_type(const struct eth_header *data_, size_t size)
+static ovs_be16
+parse_dl_type(const void **datap, size_t *sizep)
{
- const void *data = data_;
union flow_vlan_hdr vlans[FLOW_MAX_VLAN_HEADERS];
- parse_vlan(&data, &size, vlans);
+ parse_vlan(datap, sizep, vlans);
- return parse_ethertype(&data, &size);
+ return parse_ethertype(datap, sizep);
}
/* Parses and return the TCP flags in 'packet', converted to host byte order.
ovs_be16 dl_type;
uint8_t nw_frag = 0, nw_proto = 0;
- if (packet->packet_type != htonl(PT_ETH)) {
+ if (!dp_packet_is_eth(packet)) {
return 0;
}
dp_packet_reset_offsets(packet);
- data_pull(&data, &size, ETH_ADDR_LEN * 2);
- dl_type = parse_ethertype(&data, &size);
+ dl_type = parse_dl_type(&data, &size);
if (OVS_UNLIKELY(eth_type_mpls(dl_type))) {
packet->l2_5_ofs = (char *)data - frame;
}
+ packet->l3_ofs = (char *)data - frame;
if (OVS_LIKELY(dl_type == htons(ETH_TYPE_IP))) {
const struct ip_header *nh = data;
int ip_len;
return 0;
}
dp_packet_set_l2_pad_size(packet, size - tot_len);
- packet->l3_ofs = (uint16_t)((char *)nh - frame);
nw_proto = nh->ip_proto;
nw_frag = ipv4_get_nw_frag(nh);
if (OVS_UNLIKELY(!ipv6_sanity_check(nh, size))) {
return 0;
}
- packet->l3_ofs = (uint16_t)((char *)nh - frame);
data_pull(&data, &size, sizeof *nh);
plen = ntohs(nh->ip6_plen); /* Never pull padding. */
dp_packet_set_l2_pad_size(packet, size - plen);
size = plen;
const struct ovs_16aligned_ip6_frag *frag_hdr;
+ nw_proto = nh->ip6_nxt;
if (!parse_ipv6_ext_hdrs__(&data, &size, &nw_proto, &nw_frag,
&frag_hdr)) {
return 0;
}
- nw_proto = nh->ip6_nxt;
} else {
return 0;
}
{
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
match_init_catchall(flow_metadata);
if (flow->tunnel.tun_id != htonll(0)) {
if (flow->tunnel.erspan_hwid) {
match_set_tun_erspan_hwid(flow_metadata, flow->tunnel.erspan_hwid);
}
+ if (flow->tunnel.gtpu_flags) {
+ match_set_tun_gtpu_flags(flow_metadata, flow->tunnel.gtpu_flags);
+ }
+ if (flow->tunnel.gtpu_msgtype) {
+ match_set_tun_gtpu_msgtype(flow_metadata, flow->tunnel.gtpu_msgtype);
+ }
tun_metadata_get_fmd(&flow->tunnel, flow_metadata);
if (flow->metadata != htonll(0)) {
match_set_metadata(flow_metadata, flow->metadata);
memset(&wc->masks, 0x0, sizeof wc->masks);
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
if (flow_tnl_dst_is_set(&flow->tunnel)) {
if (flow->tunnel.flags & FLOW_TNL_F_KEY) {
WC_MASK_FIELD(wc, tunnel.erspan_idx);
WC_MASK_FIELD(wc, tunnel.erspan_dir);
WC_MASK_FIELD(wc, tunnel.erspan_hwid);
+ WC_MASK_FIELD(wc, tunnel.gtpu_flags);
+ WC_MASK_FIELD(wc, tunnel.gtpu_msgtype);
if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) {
if (flow->tunnel.metadata.present.map) {
flow_wc_map(const struct flow *flow, struct flowmap *map)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
flowmap_init(map);
flow_wildcards_clear_non_packet_fields(struct flow_wildcards *wc)
{
/* Update this function whenever struct flow changes. */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata);
memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
uint32_t
miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t hash = basis;
if (flow) {
uint32_t
flow_hash_5tuple(const struct flow *flow, uint32_t basis)
{
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t hash = basis;
if (flow) {
if (clear_flow_L3) {
/* Clear all L3 and L4 fields and dp_hash. */
- BUILD_ASSERT(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT(FLOW_WC_SEQ == 42);
memset((char *) flow + FLOW_SEGMENT_2_ENDS_AT, 0,
sizeof(struct flow) - FLOW_SEGMENT_2_ENDS_AT);
flow->dp_hash = 0;
igmp->igmp_code = ntohs(flow->tp_dst);
put_16aligned_be32(&igmp->group, flow->igmp_group_ip4);
} else if (flow->nw_proto == IPPROTO_ICMPV6) {
- struct icmp6_hdr *icmp = dp_packet_put_zeros(p, sizeof *icmp);
- icmp->icmp6_type = ntohs(flow->tp_src);
- icmp->icmp6_code = ntohs(flow->tp_dst);
- uint32_t *reserved = &icmp->icmp6_dataun.icmp6_un_data32[0];
- *reserved = ntohl(flow->igmp_group_ip4);
-
- if (icmp->icmp6_code == 0 &&
- (icmp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
- icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) {
+ struct icmp6_data_header *icmp6;
+
+ icmp6 = dp_packet_put_zeros(p, sizeof *icmp6);
+ icmp6->icmp6_base.icmp6_type = ntohs(flow->tp_src);
+ icmp6->icmp6_base.icmp6_code = ntohs(flow->tp_dst);
+ put_16aligned_be32(icmp6->icmp6_data.be32, flow->igmp_group_ip4);
+
+ if (icmp6->icmp6_base.icmp6_code == 0 &&
+ (icmp6->icmp6_base.icmp6_type == ND_NEIGHBOR_SOLICIT ||
+ icmp6->icmp6_base.icmp6_type == ND_NEIGHBOR_ADVERT)) {
struct in6_addr *nd_target;
struct ovs_nd_lla_opt *lla_opt;
lla_opt->type = ND_OPT_TARGET_LINKADDR;
lla_opt->mac = flow->arp_tha;
}
- } else if (icmp->icmp6_code == 0 &&
- (icmp->icmp6_type == ICMP6_ECHO_REQUEST ||
- icmp->icmp6_type == ICMP6_ECHO_REPLY)) {
+ } else if (icmp6->icmp6_base.icmp6_code == 0 &&
+ (icmp6->icmp6_base.icmp6_type == ICMP6_ECHO_REQUEST ||
+ icmp6->icmp6_base.icmp6_type == ICMP6_ECHO_REPLY)) {
flow_compose_l7(p, l7, l7_len);
} else {
/* XXX Add inner IP packet for e.g. destination unreachable? */
igmp->igmp_csum = 0;
igmp->igmp_csum = csum(igmp, l4_len);
} else if (flow->nw_proto == IPPROTO_ICMPV6) {
- struct icmp6_hdr *icmp = dp_packet_l4(p);
+ struct icmp6_data_header *icmp6 = dp_packet_l4(p);
- icmp->icmp6_cksum = 0;
- icmp->icmp6_cksum = (OVS_FORCE uint16_t)
- csum_finish(csum_continue(pseudo_hdr_csum, icmp, l4_len));
+ icmp6->icmp6_base.icmp6_cksum = 0;
+ icmp6->icmp6_base.icmp6_cksum =
+ csum_finish(csum_continue(pseudo_hdr_csum, icmp6, l4_len));
}
}
}
/* Add code to this function (or its callees) for emitting new fields or
* protocols. (This isn't essential, so it can be skipped for initial
* testing.) */
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 41);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42);
uint32_t pseudo_hdr_csum;
size_t l4_len;