VPP-19: Split the lookup.h IP_LOOKUP_NEXT enum.
[vpp.git] / vnet / vnet / map / sixrd.h
1 /*---------------------------------------------------------------------------
2  * Copyright (c) 2009-2014 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  *---------------------------------------------------------------------------
15  */
16 #include <stdbool.h>
17 #include <vppinfra/error.h>
18 #include <vnet/vnet.h>
19 #include <vnet/ip/ip.h>
20
21 int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len,
22                         ip4_address_t *ip4_prefix, u8 ip4_prefix_len,
23                         ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu);
24 int sixrd_delete_domain(u32 sixrd_domain_index);
25 u8 *format_sixrd_trace(u8 *s, va_list *args);
26
27 typedef struct {
28   ip6_address_t ip6_prefix;
29   ip4_address_t ip4_prefix;
30   ip4_address_t ip4_src;
31   u8 ip6_prefix_len;
32   u8 ip4_prefix_len;
33
34   /* helpers */
35   u8 shift;
36
37   u16 mtu;
38 } sixrd_domain_t;
39
40 typedef struct {
41   /* pool of SIXRD domains */
42   sixrd_domain_t *domains;
43
44   /* convenience */
45   vlib_main_t *vlib_main;
46   vnet_main_t *vnet_main;
47 } sixrd_main_t;
48
49 #define foreach_sixrd_error                             \
50   /* Must be first. */                                  \
51  _(NONE, "valid SIXRD packets")                         \
52  _(BAD_PROTOCOL, "bad protocol")                        \
53  _(WRONG_ICMP_TYPE, "wrong icmp type")                  \
54  _(SEC_CHECK, "security check failed")                  \
55  _(ICMP, "unable to translate ICMP")                    \
56  _(UNKNOWN, "unknown")                                  \
57  _(NO_DOMAIN, "no domain")                              \
58  _(ENCAPSULATED, "encapsulated")                        \
59  _(DECAPSULATED, "decapsulated")                        \
60  _(TRANSLATED_4TO6, "translated 4 to 6")                \
61  _(TRANSLATED_6TO4, "translated 6 to 4")                \
62  _(FRAGMENT, "fragment handling error")                 \
63  _(FRAGMENT_QUEUED, "dropped, missing first fragment")  \
64  _(FRAGMENTED, "packets requiring fragmentation")       \
65  _(FRAGMENT_PARTS, "fragment parts")                    \
66  _(MALFORMED, "malformed packet")
67
68 typedef enum {
69 #define _(sym,str) SIXRD_ERROR_##sym,
70    foreach_sixrd_error
71 #undef _
72    SIXRD_N_ERROR,
73  } sixrd_error_t;
74
75 typedef struct {
76   u32 sixrd_domain_index;
77 } sixrd_trace_t;
78
79 sixrd_main_t sixrd_main;
80
81 /*
82  * sixrd_get_addr
83  */
84 static_always_inline u32
85 sixrd_get_addr (sixrd_domain_t *d, u64 dal)
86 {
87
88   /* 1:1 mode */
89   if (d->ip4_prefix_len == 32) return (d->ip4_prefix.as_u32);
90
91   /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset ip6_prefix_len */
92   return (d->ip4_prefix.as_u32 | (u32)(dal >> d->shift));
93 }
94
95 /*
96  * Get the SIXRD domain from an IPv6 lookup adjacency.
97  */
98 static_always_inline sixrd_domain_t *
99 ip6_sixrd_get_domain (u32 adj_index, u32 *sixrd_domain_index)
100 {
101   sixrd_main_t *mm = &sixrd_main;
102   ip_lookup_main_t *lm = &ip6_main.lookup_main;
103   ip_adjacency_t *adj = ip_get_adjacency(lm, adj_index);
104   ASSERT(adj);
105   uword *p = (uword *)adj->rewrite_data;
106   ASSERT(p);
107   *sixrd_domain_index = p[0];
108   return pool_elt_at_index(mm->domains, p[0]);
109 }
110
111 /*
112  * Get the SIXRD domain from an IPv4 lookup adjacency.
113  * If the IPv4 address is not shared, no lookup is required.
114  * The IPv6 address is used otherwise.
115  */
116 static_always_inline sixrd_domain_t *
117 ip4_sixrd_get_domain (u32 adj_index, ip6_address_t *addr,
118                       u32 *sixrd_domain_index, u8 *error)
119 {
120   sixrd_main_t *mm = &sixrd_main;
121   ip6_main_t *im6 = &ip6_main;
122   ip_lookup_main_t *lm4 = &ip4_main.lookup_main;
123   ip_lookup_main_t *lm6 = &ip6_main.lookup_main;
124   ip_adjacency_t *adj = ip_get_adjacency(lm4, adj_index);
125   ASSERT(adj);
126   uword *p = (uword *)adj->rewrite_data;
127   ASSERT(p);
128   *sixrd_domain_index = p[0];
129   if (p[0] != ~0)
130     return pool_elt_at_index(mm->domains, p[0]);
131
132   u32 ai = ip6_fib_lookup_with_table(im6, 0, addr);
133   ip_adjacency_t *adj6 = ip_get_adjacency (lm6, ai);
134   if (PREDICT_TRUE(adj6->lookup_next_index == IP_LOOKUP_NEXT_SIXRD)) {
135     uword *p = (uword *)adj6->rewrite_data;
136     *sixrd_domain_index = p[0];
137     return pool_elt_at_index(mm->domains, *sixrd_domain_index);
138   }
139   *error = SIXRD_ERROR_NO_DOMAIN;
140   return NULL;
141 }