1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
/*
* det44.h - deterministic NAT definitions
*
* Copyright (c) 2020 Cisco and/or its affiliates.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* @brief Deterministic NAT (CGN) inlines
*/
#ifndef __included_det44_inlines_h__
#define __included_det44_inlines_h__
static_always_inline int
det44_is_interface_addr (vlib_node_runtime_t * node,
u32 sw_if_index0, u32 ip4_addr)
{
det44_runtime_t *rt = (det44_runtime_t *) node->runtime_data;
det44_main_t *dm = &det44_main;
ip4_address_t *first_int_addr;
if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
{
first_int_addr = ip4_interface_first_address (dm->ip4_main,
sw_if_index0, 0);
rt->cached_sw_if_index = sw_if_index0;
if (first_int_addr)
rt->cached_ip4_address = first_int_addr->as_u32;
else
rt->cached_ip4_address = 0;
}
if (PREDICT_FALSE (rt->cached_ip4_address == ip4_addr))
return 0;
return 1;
}
/**
* @brief Check if packet should be translated
*
* Packets aimed at outside interface and external address with active session
* should be translated.
*
* @param node NAT runtime data
* @param sw_if_index0 index of the inside interface
* @param ip0 IPv4 header
* @param proto0 NAT protocol
* @param rx_fib_index0 RX FIB index
*
* @returns 0 if packet should be translated otherwise 1
*/
static_always_inline int
det44_translate (vlib_node_runtime_t * node, u32 sw_if_index0,
ip4_header_t * ip0, u32 proto0, u32 rx_fib_index0)
{
det44_main_t *dm = &det44_main;
fib_node_index_t fei = FIB_NODE_INDEX_INVALID;
det44_fib_t *outside_fib;
fib_prefix_t pfx = {
.fp_proto = FIB_PROTOCOL_IP4,
.fp_len = 32,
.fp_addr = {
.ip4.as_u32 = ip0->dst_address.as_u32,
}
,
};
/* Don't NAT packet aimed at the interface address */
if (PREDICT_FALSE (!det44_is_interface_addr (node, sw_if_index0,
ip0->dst_address.as_u32)))
{
return 1;
}
/* find out if there is outside feature enabled for this destination */
fei = fib_table_lookup (rx_fib_index0, &pfx);
if (FIB_NODE_INDEX_INVALID != fei)
{
u32 sw_if_index = fib_entry_get_resolving_interface (fei);
if (sw_if_index == ~0)
{
// TODO: go over use cases
vec_foreach (outside_fib, dm->outside_fibs)
{
fei = fib_table_lookup (outside_fib->fib_index, &pfx);
if (FIB_NODE_INDEX_INVALID != fei)
{
sw_if_index = fib_entry_get_resolving_interface (fei);
if (sw_if_index != ~0)
break;
}
}
}
if (sw_if_index != ~0)
{
det44_interface_t *i;
pool_foreach (i, dm->interfaces) {
/* NAT packet aimed at outside interface */
if ((det44_interface_is_outside (i)) && (sw_if_index == i->sw_if_index))
return 0;
}
}
}
return 1;
}
#endif /* __included_det44_inlines_h__ */
/*
* fd.io coding-style-patch-verification: ON
*
* Local Variables:
* eval: (c-set-style "gnu")
* End:
*/
|