Reorganize source tree to use single autotools instance
[vpp.git] / src / plugins / sixrd / 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 #include <vnet/fib/ip6_fib.h>
21
22 #include "sixrd_dpo.h"
23
24 int sixrd_create_domain(ip6_address_t *ip6_prefix, u8 ip6_prefix_len,
25                         ip4_address_t *ip4_prefix, u8 ip4_prefix_len,
26                         ip4_address_t *ip4_src, u32 *sixrd_domain_index, u16 mtu);
27 int sixrd_delete_domain(u32 sixrd_domain_index);
28 u8 *format_sixrd_trace(u8 *s, va_list *args);
29
30 typedef struct {
31   ip6_address_t ip6_prefix;
32   ip4_address_t ip4_prefix;
33   ip4_address_t ip4_src;
34   u8 ip6_prefix_len;
35   u8 ip4_prefix_len;
36
37   /* helpers */
38   u8 shift;
39
40   u16 mtu;
41 } sixrd_domain_t;
42
43 typedef struct {
44   /* pool of SIXRD domains */
45   sixrd_domain_t *domains;
46
47   /* convenience */
48   vlib_main_t *vlib_main;
49   vnet_main_t *vnet_main;
50 } sixrd_main_t;
51
52 #define foreach_sixrd_error                             \
53   /* Must be first. */                                  \
54  _(NONE, "valid SIXRD packets")                         \
55  _(BAD_PROTOCOL, "bad protocol")                        \
56  _(WRONG_ICMP_TYPE, "wrong icmp type")                  \
57  _(SEC_CHECK, "security check failed")                  \
58  _(ICMP, "unable to translate ICMP")                    \
59  _(UNKNOWN, "unknown")                                  \
60  _(NO_DOMAIN, "no domain")                              \
61  _(ENCAPSULATED, "encapsulated")                        \
62  _(DECAPSULATED, "decapsulated")                        \
63  _(TRANSLATED_4TO6, "translated 4 to 6")                \
64  _(TRANSLATED_6TO4, "translated 6 to 4")                \
65  _(FRAGMENT, "fragment handling error")                 \
66  _(FRAGMENT_QUEUED, "dropped, missing first fragment")  \
67  _(FRAGMENTED, "packets requiring fragmentation")       \
68  _(FRAGMENT_PARTS, "fragment parts")                    \
69  _(MALFORMED, "malformed packet")
70
71 typedef enum {
72 #define _(sym,str) SIXRD_ERROR_##sym,
73    foreach_sixrd_error
74 #undef _
75    SIXRD_N_ERROR,
76  } sixrd_error_t;
77
78 typedef struct {
79   u32 sixrd_domain_index;
80 } sixrd_trace_t;
81
82 sixrd_main_t sixrd_main;
83
84 /*
85  * sixrd_get_addr
86  */
87 static_always_inline u32
88 sixrd_get_addr (sixrd_domain_t *d, u64 dal)
89 {
90
91   /* 1:1 mode */
92   if (d->ip4_prefix_len == 32) return (d->ip4_prefix.as_u32);
93
94   /* Grab 32 - ip4_prefix_len bits out of IPv6 address from offset ip6_prefix_len */
95   return (d->ip4_prefix.as_u32 | (u32)(dal >> d->shift));
96 }
97
98 /*
99  * Get the SIXRD domain from an IPv6 lookup adjacency.
100  */
101 static_always_inline sixrd_domain_t *
102 ip6_sixrd_get_domain (u32 sdi, u32 *sixrd_domain_index)
103 {
104   sixrd_main_t *mm = &sixrd_main;
105   sixrd_dpo_t *sd;
106
107   sd = sixrd_dpo_get(sdi);
108
109   ASSERT(sd);
110   *sixrd_domain_index = sd->sd_domain;
111   return pool_elt_at_index(mm->domains, *sixrd_domain_index);
112 }
113
114 /*
115  * Get the SIXRD domain from an IPv4 lookup adjacency.
116  * If the IPv4 address is not shared, no lookup is required.
117  * The IPv6 address is used otherwise.
118  */
119 static_always_inline sixrd_domain_t *
120 ip4_sixrd_get_domain (u32 sdi, ip6_address_t *addr,
121                       u32 *sixrd_domain_index, u8 *error)
122 {
123   sixrd_main_t *mm = &sixrd_main;
124   sixrd_dpo_t *sd;
125
126   sd = sixrd_dpo_get(sdi);
127   *sixrd_domain_index = sd->sd_domain;
128   if (*sixrd_domain_index != ~0)
129     return pool_elt_at_index(mm->domains, *sixrd_domain_index);
130
131   u32 lbi = ip6_fib_table_fwding_lookup(&ip6_main, 0, addr);
132   const dpo_id_t *dpo = load_balance_get_bucket(lbi, 0);
133   if (PREDICT_TRUE(dpo->dpoi_type == sixrd_dpo_type))
134     {
135       sd = sixrd_dpo_get(dpo->dpoi_index);
136       *sixrd_domain_index = sd->sd_domain;
137       return pool_elt_at_index(mm->domains, *sixrd_domain_index);
138     }
139   *error = SIXRD_ERROR_NO_DOMAIN;
140   return NULL;
141 }