-/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc.
+/* Copyright (c) 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.
struct xlate_out {
enum slow_path_reason slow; /* 0 if fast path may be used. */
- bool fail_open; /* Initial rule is fail open? */
- bool has_learn; /* Actions include NXAST_LEARN? */
- bool has_normal; /* Actions output to OFPP_NORMAL? */
- bool has_fin_timeout; /* Actions include NXAST_FIN_TIMEOUT? */
- ofp_port_t nf_output_iface; /* Output interface index for NetFlow. */
- mirror_mask_t mirrors; /* Bitmap of associated mirrors. */
-
- /* Recirculation IDs on which references are held. */
- unsigned n_recircs;
- union {
- uint32_t recirc[2]; /* When n_recircs == 1 or 2 */
- uint32_t *recircs; /* When 'n_recircs' > 2 */
- };
-};
-/* Helpers to abstract the recirculation union away. */
-static inline void
-xlate_out_add_recirc(struct xlate_out *xout, uint32_t id)
-{
- if (OVS_LIKELY(xout->n_recircs < ARRAY_SIZE(xout->recirc))) {
- xout->recirc[xout->n_recircs++] = id;
- } else {
- if (xout->n_recircs == ARRAY_SIZE(xout->recirc)) {
- uint32_t *recircs = xmalloc(sizeof xout->recirc + sizeof id);
-
- memcpy(recircs, xout->recirc, sizeof xout->recirc);
- xout->recircs = recircs;
- } else {
- xout->recircs = xrealloc(xout->recircs,
- (xout->n_recircs + 1) * sizeof id);
- }
- xout->recircs[xout->n_recircs++] = id;
- }
-}
-
-static inline const uint32_t *
-xlate_out_get_recircs(const struct xlate_out *xout)
-{
- if (OVS_LIKELY(xout->n_recircs <= ARRAY_SIZE(xout->recirc))) {
- return xout->recirc;
- } else {
- return xout->recircs;
- }
-}
-
-static inline void
-xlate_out_take_recircs(struct xlate_out *xout)
-{
- if (OVS_UNLIKELY(xout->n_recircs > ARRAY_SIZE(xout->recirc))) {
- free(xout->recircs);
- }
- xout->n_recircs = 0;
-}
-
-static inline void
-xlate_out_free_recircs(struct xlate_out *xout)
-{
- if (OVS_LIKELY(xout->n_recircs <= ARRAY_SIZE(xout->recirc))) {
- for (int i = 0; i < xout->n_recircs; i++) {
- recirc_free_id(xout->recirc[i]);
- }
- } else {
- for (int i = 0; i < xout->n_recircs; i++) {
- recirc_free_id(xout->recircs[i]);
- }
- free(xout->recircs);
- }
-}
+ struct recirc_refs recircs; /* Recirc action IDs on which references are
+ * held. */
+};
struct xlate_in {
struct ofproto_dpif *ofproto;
* calling xlate_in_init(). */
const struct dpif_flow_stats *resubmit_stats;
+ /* Recursion and resubmission levels carried over from a pre-existing
+ * translation of a related flow. An example of when this can occur is
+ * the translation of an ARP packet that was generated as the result of
+ * outputting to a tunnel port. In this case, the original flow going to
+ * the tunnel is the related flow. Since the two flows are different, they
+ * should not use the same xlate_ctx structure. However, we still need
+ * limit the maximum recursion across the entire translation.
+ *
+ * These fields are normally set to zero, so the client has to set them
+ * manually after calling xlate_in_init(). In that case, they should be
+ * copied from the same-named fields in the related flow's xlate_ctx. */
+ int recurse;
+ int resubmits;
+
/* If nonnull, flow translation populates this cache with references to all
* modules that are affected by translation. This 'xlate_cache' may be
* passed to xlate_push_stats() to perform the same function as
/* The recirculation context related to this translation, as returned by
* xlate_lookup. */
- const struct recirc_id_node *recirc;
+ const struct recirc_state *recirc;
};
void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct dpif *,
struct dpif_sflow **, struct netflow **,
ofp_port_t *ofp_in_port);
-void xlate_actions(struct xlate_in *, struct xlate_out *);
+enum xlate_error {
+ XLATE_OK = 0,
+ XLATE_BRIDGE_NOT_FOUND,
+ XLATE_RECURSION_TOO_DEEP,
+ XLATE_TOO_MANY_RESUBMITS,
+ XLATE_STACK_TOO_DEEP,
+ XLATE_NO_RECIRCULATION_CONTEXT,
+ XLATE_RECIRCULATION_CONFLICT,
+ XLATE_TOO_MANY_MPLS_LABELS,
+};
+
+const char *xlate_strerror(enum xlate_error error);
+
+enum xlate_error xlate_actions(struct xlate_in *, struct xlate_out *);
+
void xlate_in_init(struct xlate_in *, struct ofproto_dpif *,
const struct flow *, ofp_port_t in_port, struct rule_dpif *,
uint16_t tcp_flags, const struct dp_packet *packet,