Line data Source code
1 : /*
2 : * Copyright (c) 2016 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 : * @brief
17 : * The data-path object representing receiveing the packet, i.e. it's for-us
18 : */
19 : #include <vlib/vlib.h>
20 : #include <vnet/ip/ip.h>
21 : #include <vnet/dpo/receive_dpo.h>
22 :
23 : /**
24 : * @brief pool of all receive DPOs
25 : */
26 : receive_dpo_t *receive_dpo_pool;
27 :
28 : int
29 155882 : dpo_is_receive (const dpo_id_t *dpo)
30 : {
31 155882 : return (dpo->dpoi_type == DPO_RECEIVE);
32 : }
33 :
34 : static receive_dpo_t *
35 20822 : receive_dpo_alloc (void)
36 : {
37 : receive_dpo_t *rd;
38 : vlib_main_t *vm;
39 : u8 did_barrier_sync;
40 :
41 20822 : dpo_pool_barrier_sync (vm, receive_dpo_pool, did_barrier_sync);
42 20822 : pool_get_aligned(receive_dpo_pool, rd, CLIB_CACHE_LINE_BYTES);
43 20822 : dpo_pool_barrier_release (vm, did_barrier_sync);
44 :
45 20822 : clib_memset(rd, 0, sizeof(*rd));
46 :
47 20822 : return (rd);
48 : }
49 :
50 : static receive_dpo_t *
51 555211 : receive_dpo_get_from_dpo (const dpo_id_t *dpo)
52 : {
53 555211 : ASSERT(DPO_RECEIVE == dpo->dpoi_type);
54 :
55 555211 : return (receive_dpo_get(dpo->dpoi_index));
56 : }
57 :
58 :
59 : /*
60 : * receive_dpo_add_or_lock
61 : *
62 : * The next_hop address here is used for source address selection in the DP.
63 : * The local adj is added to an interface's receive prefix, the next-hop
64 : * passed here is the local prefix on the same interface.
65 : */
66 : void
67 20822 : receive_dpo_add_or_lock (dpo_proto_t proto,
68 : u32 sw_if_index,
69 : const ip46_address_t *nh_addr,
70 : dpo_id_t *dpo)
71 : {
72 : receive_dpo_t *rd;
73 :
74 20822 : rd = receive_dpo_alloc();
75 :
76 20822 : rd->rd_sw_if_index = sw_if_index;
77 20822 : if (NULL != nh_addr)
78 : {
79 20822 : rd->rd_addr = *nh_addr;
80 : }
81 :
82 20822 : dpo_set(dpo, DPO_RECEIVE, proto, (rd - receive_dpo_pool));
83 20822 : }
84 :
85 : static void
86 281642 : receive_dpo_lock (dpo_id_t *dpo)
87 : {
88 : receive_dpo_t *rd;
89 :
90 281642 : rd = receive_dpo_get_from_dpo(dpo);
91 281642 : rd->rd_locks++;
92 281642 : }
93 :
94 : static void
95 273569 : receive_dpo_unlock (dpo_id_t *dpo)
96 : {
97 : receive_dpo_t *rd;
98 :
99 273569 : rd = receive_dpo_get_from_dpo(dpo);
100 273569 : rd->rd_locks--;
101 :
102 273569 : if (0 == rd->rd_locks)
103 : {
104 16786 : pool_put(receive_dpo_pool, rd);
105 : }
106 273569 : }
107 :
108 : static u8*
109 2304 : format_receive_dpo (u8 *s, va_list *ap)
110 : {
111 2304 : CLIB_UNUSED(index_t index) = va_arg(*ap, index_t);
112 2304 : CLIB_UNUSED(u32 indent) = va_arg(*ap, u32);
113 2304 : vnet_main_t * vnm = vnet_get_main();
114 : receive_dpo_t *rd;
115 :
116 2304 : if (pool_is_free_index(receive_dpo_pool, index))
117 : {
118 1 : return (format(s, "dpo-receive DELETED"));
119 : }
120 :
121 2303 : rd = receive_dpo_get(index);
122 :
123 2303 : if (~0 != rd->rd_sw_if_index)
124 : {
125 515 : return (format(s, "dpo-receive: %U on %U",
126 : format_ip46_address, &rd->rd_addr, IP46_TYPE_ANY,
127 : format_vnet_sw_interface_name, vnm,
128 : vnet_get_sw_interface(vnm, rd->rd_sw_if_index)));
129 : }
130 : else
131 : {
132 1788 : return (format(s, "dpo-receive"));
133 : }
134 : }
135 :
136 : static void
137 0 : receive_dpo_mem_show (void)
138 : {
139 0 : fib_show_memory_usage("Receive",
140 0 : pool_elts(receive_dpo_pool),
141 0 : pool_len(receive_dpo_pool),
142 : sizeof(receive_dpo_t));
143 0 : }
144 :
145 : const static dpo_vft_t receive_vft = {
146 : .dv_lock = receive_dpo_lock,
147 : .dv_unlock = receive_dpo_unlock,
148 : .dv_format = format_receive_dpo,
149 : .dv_mem_show = receive_dpo_mem_show,
150 : };
151 :
152 : /**
153 : * @brief The per-protocol VLIB graph nodes that are assigned to a receive
154 : * object.
155 : *
156 : * this means that these graph nodes are ones from which a receive is the
157 : * parent object in the DPO-graph.
158 : */
159 : const static char *const receive_ip4_nodes[] = {
160 : "ip4-receive",
161 : NULL,
162 : };
163 : const static char *const receive_ip6_nodes[] = {
164 : "ip6-receive",
165 : NULL,
166 : };
167 :
168 : const static char* const * const receive_nodes[DPO_PROTO_NUM] =
169 : {
170 : [DPO_PROTO_IP4] = receive_ip4_nodes,
171 : [DPO_PROTO_IP6] = receive_ip6_nodes,
172 : [DPO_PROTO_MPLS] = NULL,
173 : };
174 :
175 : void
176 559 : receive_dpo_module_init (void)
177 : {
178 559 : dpo_register(DPO_RECEIVE, &receive_vft, receive_nodes);
179 559 : }
|