6RD: Rewritten 6RD RFC5969 support.
[vpp.git] / src / plugins / sixrd / sixrd.h
index f911461..f443c03 100644 (file)
  *---------------------------------------------------------------------------
  */
 #include <stdbool.h>
-#include <vppinfra/error.h>
-#include <vnet/vnet.h>
-#include <vnet/ip/ip.h>
 #include <vnet/fib/ip6_fib.h>
+#include <vnet/ip/ip.h>
+#include <vnet/vnet.h>
+#include <vppinfra/error.h>
 
-#include "sixrd_dpo.h"
-
-int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len,
-                       ip4_address_t *ip4_prefix, u8 ip4_prefix_len,
-                       ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu);
-int sixrd_delete_domain(u32 sixrd_domain_index);
-u8 *format_sixrd_trace(u8 *s, va_list *args);
+#define SIXRD_DEFAULT_MTU 1480 /* 1500 - IPv4 header */
 
-typedef struct {
+typedef struct
+{
+  u32 fib_index;
+  u32 hw_if_index;
+  u32 sw_if_index;
+  u32 tunnel_index;
   ip6_address_t ip6_prefix;
   ip4_address_t ip4_prefix;
   ip4_address_t ip4_src;
@@ -38,46 +37,35 @@ typedef struct {
   u8 shift;
 
   u16 mtu;
-} sixrd_domain_t;
+  bool security_check;
+} sixrd_tunnel_t;
+
+typedef struct
+{
+  u16 msg_id_base;
 
-typedef struct {
   /* pool of SIXRD domains */
-  sixrd_domain_t *domains;
+  sixrd_tunnel_t *tunnels;
+  u32 *tunnel_index_by_sw_if_index;
+  uword *tunnel_by_ip;
 
-  /* convenience */
-  vlib_main_t *vlib_main;
-  vnet_main_t *vnet_main;
 } sixrd_main_t;
 
-#define foreach_sixrd_error                            \
-  /* Must be first. */                                 \
- _(NONE, "valid SIXRD packets")                                \
- _(BAD_PROTOCOL, "bad protocol")                       \
- _(WRONG_ICMP_TYPE, "wrong icmp type")                 \
- _(SEC_CHECK, "security check failed")                 \
- _(ICMP, "unable to translate ICMP")                   \
- _(UNKNOWN, "unknown")                                 \
- _(NO_DOMAIN, "no domain")                             \
- _(ENCAPSULATED, "encapsulated")                       \
- _(DECAPSULATED, "decapsulated")                       \
- _(TRANSLATED_4TO6, "translated 4 to 6")               \
- _(TRANSLATED_6TO4, "translated 6 to 4")               \
- _(FRAGMENT, "fragment handling error")                        \
- _(FRAGMENT_QUEUED, "dropped, missing first fragment") \
- _(FRAGMENTED, "packets requiring fragmentation")      \
- _(FRAGMENT_PARTS, "fragment parts")                    \
- _(MALFORMED, "malformed packet")
-
-typedef enum {
-#define _(sym,str) SIXRD_ERROR_##sym,
-   foreach_sixrd_error
-#undef _
-   SIXRD_N_ERROR,
- } sixrd_error_t;
+#define foreach_sixrd_error                                                    \
+  /* Must be first. */                                                         \
+  _(NONE, "valid SIXRD packets")                                               \
+  _(BAD_PROTOCOL, "bad protocol")                                              \
+  _(SEC_CHECK, "security check failed")                                        \
+  _(NO_TUNNEL, "no tunnel")
 
-typedef struct {
-  u32 sixrd_domain_index;
-} sixrd_trace_t;
+
+typedef enum
+{
+#define _(sym, str) SIXRD_ERROR_##sym,
+  foreach_sixrd_error
+#undef _
+    SIXRD_N_ERROR,
+} sixrd_error_t;
 
 extern sixrd_main_t sixrd_main;
 
@@ -85,57 +73,51 @@ extern sixrd_main_t sixrd_main;
  * sixrd_get_addr
  */
 static_always_inline u32
-sixrd_get_addr (sixrd_domain_t *d, u64 dal)
+sixrd_get_addr_net (const sixrd_tunnel_t * t, u64 dal)
 {
-
   /* 1:1 mode */
-  if (d->ip4_prefix_len == 32) return (d->ip4_prefix.as_u32);
-
-  /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset ip6_prefix_len */
-  return (d->ip4_prefix.as_u32 | (u32)(dal >> d->shift));
+  if (t->ip4_prefix_len == 32)
+    return (t->ip4_prefix.as_u32);
+
+  dal = clib_net_to_host_u64 (dal);
+
+  /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset
+   * ip6_prefix_len */
+  u32 mask = ~(~0ULL << (32 - t->ip4_prefix_len));
+  u32 ip4 =
+    clib_net_to_host_u32 (t->
+                         ip4_prefix.as_u32) | ((u32) (dal >> t->
+                                                      shift) & mask);
+  return clib_host_to_net_u32 (ip4);
 }
 
-/*
- * Get the SIXRD domain from an IPv6 lookup adjacency.
- */
-static_always_inline sixrd_domain_t *
-ip6_sixrd_get_domain (u32 sdi, u32 *sixrd_domain_index)
+static_always_inline sixrd_tunnel_t *
+find_tunnel_by_ip4_address (ip4_address_t * ip)
 {
-  sixrd_main_t *mm = &sixrd_main;
-  sixrd_dpo_t *sd;
-
-  sd = sixrd_dpo_get(sdi);
-
-  ASSERT(sd);
-  *sixrd_domain_index = sd->sd_domain;
-  return pool_elt_at_index(mm->domains, *sixrd_domain_index);
+  sixrd_main_t *sm = &sixrd_main;
+  uword *p;
+  p = hash_get (sm->tunnel_by_ip, ip->as_u32);
+  if (!p)
+    return NULL;
+  return pool_elt_at_index (sm->tunnels, p[0]);
 }
 
-/*
- * Get the SIXRD domain from an IPv4 lookup adjacency.
- * If the IPv4 address is not shared, no lookup is required.
- * The IPv6 address is used otherwise.
- */
-static_always_inline sixrd_domain_t *
-ip4_sixrd_get_domain (u32 sdi, ip6_address_t *addr,
-                     u32 *sixrd_domain_index, u8 *error)
+static_always_inline sixrd_tunnel_t *
+ip4_sixrd_get_tunnel (u32 sdi, ip4_address_t * addr, u8 * error)
 {
-  sixrd_main_t *mm = &sixrd_main;
-  sixrd_dpo_t *sd;
-
-  sd = sixrd_dpo_get(sdi);
-  *sixrd_domain_index = sd->sd_domain;
-  if (*sixrd_domain_index != ~0)
-    return pool_elt_at_index(mm->domains, *sixrd_domain_index);
-
-  u32 lbi = ip6_fib_table_fwding_lookup(&ip6_main, 0, addr);
-  const dpo_id_t *dpo = load_balance_get_bucket(lbi, 0);
-  if (PREDICT_TRUE(dpo->dpoi_type == sixrd_dpo_type))
+  sixrd_tunnel_t *t = find_tunnel_by_ip4_address (addr);
+  if (!t)
     {
-      sd = sixrd_dpo_get(dpo->dpoi_index);
-      *sixrd_domain_index = sd->sd_domain;
-      return pool_elt_at_index(mm->domains, *sixrd_domain_index);
+      *error = SIXRD_ERROR_NO_TUNNEL;
+      return NULL;
     }
-  *error = SIXRD_ERROR_NO_DOMAIN;
-  return NULL;
+  return t;
 }
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */