summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/openvswitch/match.h1
-rw-r--r--include/openvswitch/tun-metadata.h5
-rw-r--r--lib/match.c7
-rw-r--r--lib/tun-metadata.c17
4 files changed, 29 insertions, 1 deletions
diff --git a/include/openvswitch/match.h b/include/openvswitch/match.h
index 61a67de2c..e5cf1a0d7 100644
--- a/include/openvswitch/match.h
+++ b/include/openvswitch/match.h
@@ -242,6 +242,7 @@ struct minimatch {
};
struct miniflow *flows[2];
};
+ struct tun_metadata_allocation *tun_md;
};
void minimatch_init(struct minimatch *, const struct match *);
diff --git a/include/openvswitch/tun-metadata.h b/include/openvswitch/tun-metadata.h
index 935c5c495..dc0312ecb 100644
--- a/include/openvswitch/tun-metadata.h
+++ b/include/openvswitch/tun-metadata.h
@@ -101,6 +101,11 @@ struct tun_metadata_allocation {
bool valid; /* Set to true after any allocation occurs. */
};
+struct tun_metadata_allocation *tun_metadata_allocation_clone(
+ const struct tun_metadata_allocation *);
+void tun_metadata_allocation_copy(struct tun_metadata_allocation *,
+ const struct tun_metadata_allocation *);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/match.c b/lib/match.c
index 97a528299..3eab0fd5d 100644
--- a/lib/match.c
+++ b/lib/match.c
@@ -1663,6 +1663,8 @@ minimatch_init(struct minimatch *dst, const struct match *src)
miniflow_alloc(dst->flows, 2, &tmp);
miniflow_init(dst->flow, &src->flow);
minimask_init(dst->mask, &src->wc);
+
+ dst->tun_md = tun_metadata_allocation_clone(&src->tun_md);
}
/* Initializes 'dst' as a copy of 'src'. The caller must eventually free 'dst'
@@ -1677,6 +1679,7 @@ minimatch_clone(struct minimatch *dst, const struct minimatch *src)
miniflow_get_values(src->flow), data_size);
memcpy(miniflow_values(&dst->mask->masks),
miniflow_get_values(&src->mask->masks), data_size);
+ dst->tun_md = tun_metadata_allocation_clone(src->tun_md);
}
/* Initializes 'dst' with the data in 'src', destroying 'src'. The caller must
@@ -1686,6 +1689,7 @@ minimatch_move(struct minimatch *dst, struct minimatch *src)
{
dst->flow = src->flow;
dst->mask = src->mask;
+ dst->tun_md = src->tun_md;
}
/* Frees any memory owned by 'match'. Does not free the storage in which
@@ -1694,6 +1698,7 @@ void
minimatch_destroy(struct minimatch *match)
{
free(match->flow);
+ free(match->tun_md);
}
/* Initializes 'dst' as a copy of 'src'. */
@@ -1702,7 +1707,7 @@ minimatch_expand(const struct minimatch *src, struct match *dst)
{
miniflow_expand(src->flow, &dst->flow);
minimask_expand(src->mask, &dst->wc);
- memset(&dst->tun_md, 0, sizeof dst->tun_md);
+ tun_metadata_allocation_copy(&dst->tun_md, src->tun_md);
}
/* Returns true if 'a' and 'b' match the same packets, false otherwise. */
diff --git a/lib/tun-metadata.c b/lib/tun-metadata.c
index c0d9180e0..f8a0e1952 100644
--- a/lib/tun-metadata.c
+++ b/lib/tun-metadata.c
@@ -924,3 +924,20 @@ tun_metadata_match_format(struct ds *s, const struct match *match)
ds_put_char(s, ',');
}
}
+
+struct tun_metadata_allocation *
+tun_metadata_allocation_clone(const struct tun_metadata_allocation *src)
+{
+ return src && src->valid ? xmemdup(src, sizeof *src) : NULL;
+}
+
+void
+tun_metadata_allocation_copy(struct tun_metadata_allocation *dst,
+ const struct tun_metadata_allocation *src)
+{
+ if (src && src->valid) {
+ *dst = *src;
+ } else {
+ memset(dst, 0, sizeof *dst);
+ }
+}