(icmp->icmp6_type == ND_NEIGHBOR_SOLICIT ||
icmp->icmp6_type == ND_NEIGHBOR_ADVERT)) {
- *nd_target = data_try_pull(datap, sizep, sizeof *nd_target);
+ *nd_target = data_try_pull(datap, sizep, sizeof **nd_target);
if (OVS_UNLIKELY(!*nd_target)) {
return false;
}
memset(arp_buf, 0, sizeof arp_buf);
if (OVS_LIKELY(parse_icmpv6(&data, &size, icmp, &nd_target,
arp_buf))) {
+ miniflow_push_words(mf, arp_sha, arp_buf,
+ ETH_ADDR_LEN * 2 / 4);
if (nd_target) {
miniflow_push_words(mf, nd_target, nd_target,
sizeof *nd_target / 4);
}
- miniflow_push_words(mf, arp_sha, arp_buf,
- ETH_ADDR_LEN * 2 / 4);
miniflow_push_be16(mf, tp_src, htons(icmp->icmp6_type));
miniflow_push_be16(mf, tp_dst, htons(icmp->icmp6_code));
}
l4_len = flow_compose_l4(b, flow);
+ ip = ofpbuf_l3(b);
ip->ip_tot_len = htons(b->l4_ofs - b->l3_ofs + l4_len);
ip->ip_csum = csum(ip, sizeof *ip);
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
l4_len = flow_compose_l4(b, flow);
+ nh = ofpbuf_l3(b);
nh->ip6_plen = htons(l4_len);
} else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
flow->dl_type == htons(ETH_TYPE_RARP)) {
static uint32_t *
miniflow_alloc_values(struct miniflow *flow, int n)
{
- if (n <= sizeof flow->inline_values / sizeof(uint32_t)) {
+ int size = MINIFLOW_VALUES_SIZE(n);
+
+ if (size <= sizeof flow->inline_values) {
flow->values_inline = true;
return flow->inline_values;
} else {
COVERAGE_INC(miniflow_malloc);
flow->values_inline = false;
- flow->offline_values = xmalloc(n * sizeof(uint32_t));
+ flow->offline_values = xmalloc(size);
return flow->offline_values;
}
}
void
miniflow_clone(struct miniflow *dst, const struct miniflow *src)
{
- int n = miniflow_n_values(src);
+ int size = MINIFLOW_VALUES_SIZE(miniflow_n_values(src));
+ uint32_t *values;
+
dst->map = src->map;
- memcpy(miniflow_alloc_values(dst, n), miniflow_get_values(src),
- n * sizeof(uint32_t));
+ if (size <= sizeof dst->inline_values) {
+ dst->values_inline = true;
+ values = dst->inline_values;
+ } else {
+ dst->values_inline = false;
+ COVERAGE_INC(miniflow_malloc);
+ dst->offline_values = xmalloc(size);
+ values = dst->offline_values;
+ }
+ memcpy(values, miniflow_get_values(src), size);
+}
+
+/* Initializes 'dst' as a copy of 'src'. The caller must have allocated
+ * 'dst' to have inline space all data in 'src'. */
+void
+miniflow_clone_inline(struct miniflow *dst, const struct miniflow *src,
+ size_t n_values)
+{
+ dst->values_inline = true;
+ dst->map = src->map;
+ memcpy(dst->inline_values, miniflow_get_values(src),
+ MINIFLOW_VALUES_SIZE(n_values));
}
/* Initializes 'dst' with the data in 'src', destroying 'src'.
- * The caller must eventually free 'dst' with miniflow_destroy(). */
+ * The caller must eventually free 'dst' with miniflow_destroy().
+ * 'dst' must be regularly sized miniflow, but 'src' can have
+ * larger than default inline values. */
void
miniflow_move(struct miniflow *dst, struct miniflow *src)
{
- *dst = *src;
+ int size = MINIFLOW_VALUES_SIZE(miniflow_n_values(src));
+
+ dst->map = src->map;
+ if (size <= sizeof dst->inline_values) {
+ dst->values_inline = true;
+ memcpy(dst->inline_values, miniflow_get_values(src), size);
+ miniflow_destroy(src);
+ } else if (src->values_inline) {
+ dst->values_inline = false;
+ COVERAGE_INC(miniflow_malloc);
+ dst->offline_values = xmalloc(size);
+ memcpy(dst->offline_values, src->inline_values, size);
+ } else {
+ dst->values_inline = false;
+ dst->offline_values = src->offline_values;
+ }
}
/* Frees any memory owned by 'flow'. Does not free the storage in which 'flow'