#include <stdint.h>
-#include "dynamic-string.h"
+#include "openvswitch/dynamic-string.h"
#include "netlink.h"
-#include "ofpbuf.h"
+#include "openvswitch/ofpbuf.h"
#include "openflow/openflow.h"
+#include "openvswitch/tun-metadata.h"
+struct flow_tnl;
struct match;
struct mf_field;
union mf_value;
-struct ofputil_geneve_table_mod;
-struct ofputil_geneve_table_reply;
+struct ofputil_tlv_table_mod;
+struct ofputil_tlv_table_reply;
struct tun_table;
-#define TUN_METADATA_NUM_OPTS 64
-#define TUN_METADATA_TOT_OPT_SIZE 256
+struct tun_table *tun_metadata_alloc(const struct tun_table *old_map);
+void tun_metadata_free(struct tun_table *);
+void tun_metadata_postpone_free(struct tun_table *);
-/* Tunnel option data, plus metadata to aid in their interpretation.
- *
- * 'opt_map' is indexed by type, that is, by the <i> in TUN_METADATA<i>, so
- * that e.g. TUN_METADATA5 is present if 'opt_map & (1ULL << 5)' is nonzero.
- * The actual data for TUN_METADATA5, if present, might be anywhere in 'opts'
- * (not necessarily even contiguous), and finding it requires referring to
- * 'tab'. */
-struct tun_metadata {
- uint8_t opts[TUN_METADATA_TOT_OPT_SIZE]; /* Values from tunnel TLVs. */
- uint64_t opt_map; /* 1-bit for each present TLV. */
- struct tun_table *tab; /* Types & lengths for 'opts' and 'opt_map'. */
- uint8_t pad[sizeof(uint64_t) - sizeof(struct tun_table *)]; /* Make 8 bytes */
-};
-BUILD_ASSERT_DECL(sizeof(((struct tun_metadata *)0)->opt_map) * 8 >=
- TUN_METADATA_NUM_OPTS);
-
-/* The location of an option can be stored either as a single offset/len
- * pair (hopefully) or if the address space is fragmented then it is a
- * linked list of these blocks. */
-struct tun_metadata_loc_chain {
- struct tun_metadata_loc_chain *next;
- uint8_t offset; /* In bytes, from start of 'opts', multiple of 4. */
- uint8_t len; /* In bytes, multiple of 4. */
-};
-
-struct tun_metadata_loc {
- int len; /* Sum of 'len' over elements in chain. */
- struct tun_metadata_loc_chain c;
-};
-
-/* Allocation of options inside struct match. This is important if we don't
- * have access to a global allocation table - either because there isn't one
- * (ovs-ofctl) or if we need to keep the allocation outside of packet
- * processing context (Packet-In). These structures never have dynamically
- * allocated memory because the address space is never fragmented. */
-struct tun_metadata_allocation {
- struct tun_metadata_loc loc[TUN_METADATA_NUM_OPTS];
- uint8_t alloc_offset; /* Byte offset into 'opts', multiple of 4. */
- bool valid; /* Set to true after any allocation occurs. */
-};
-
-void tun_metadata_init(void);
+enum ofperr tun_metadata_table_mod(struct ofputil_tlv_table_mod *,
+ const struct tun_table *old_tab,
+ struct tun_table **new_tab);
+void tun_metadata_table_request(const struct tun_table *,
+ struct ofputil_tlv_table_reply *);
-enum ofperr tun_metadata_table_mod(struct ofputil_geneve_table_mod *);
-void tun_metadata_table_request(struct ofputil_geneve_table_reply *);
-
-void tun_metadata_read(const struct tun_metadata *,
+void tun_metadata_read(const struct flow_tnl *,
const struct mf_field *, union mf_value *);
-void tun_metadata_write(struct tun_metadata *,
+void tun_metadata_write(struct flow_tnl *,
const struct mf_field *, const union mf_value *);
+void tun_metadata_delete(struct flow_tnl *, const struct mf_field *);
void tun_metadata_set_match(const struct mf_field *,
const union mf_value *value,
- const union mf_value *mask, struct match *);
-void tun_metadata_get_fmd(const struct tun_metadata *,
- struct match *flow_metadata);
+ const union mf_value *mask, struct match *,
+ char **err_str);
+void tun_metadata_get_fmd(const struct flow_tnl *, struct match *flow_metadata);
+
+void tun_metadata_from_geneve_nlattr(const struct nlattr *attr, bool is_mask,
+ struct flow_tnl *tun);
+void tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun,
+ const struct flow_tnl *flow,
+ const struct ofpbuf *key,
+ struct ofpbuf *);
+
+int tun_metadata_from_geneve_udpif(const struct tun_table *,
+ const struct flow_tnl *flow,
+ const struct flow_tnl *src,
+ struct flow_tnl *dst);
+void tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src,
+ const struct flow_tnl *mask_src,
+ const struct geneve_opt *flow_src_opt,
+ int opts_len, struct geneve_opt *dst);
+
+int tun_metadata_to_geneve_header(const struct flow_tnl *flow,
+ struct geneve_opt *, bool *crit_opt);
-int tun_metadata_from_geneve_nlattr(const struct nlattr *attr,
- const struct nlattr *flow_attrs,
- size_t flow_attr_len,
- const struct tun_metadata *flow_metadata,
- struct tun_metadata *metadata);
-void tun_metadata_to_geneve_nlattr_flow(const struct tun_metadata *flow,
- struct ofpbuf *);
-void tun_metadata_to_geneve_nlattr_mask(const struct ofpbuf *key,
- const struct tun_metadata *mask,
- const struct tun_metadata *flow,
- struct ofpbuf *);
void tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm,
const struct match *);
void tun_metadata_match_format(struct ds *, const struct match *);