FIB: return entry prefix by const reference to avoid the copy
[vpp.git] / src / plugins / gbp / gbp_subnet.c
1 /*
2  * Copyright (c) 2018 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 <plugins/gbp/gbp.h>
17 #include <plugins/gbp/gbp_fwd_dpo.h>
18 #include <plugins/gbp/gbp_policy_dpo.h>
19
20 #include <vnet/fib/fib_table.h>
21 #include <vnet/dpo/load_balance.h>
22
23 static int
24 gbp_internal_subnet_add (u32 fib_index, const fib_prefix_t * pfx)
25 {
26   dpo_id_t gfd = DPO_INVALID;
27
28   gbp_fwd_dpo_add_or_lock (fib_proto_to_dpo (pfx->fp_proto), &gfd);
29
30   fib_table_entry_special_dpo_update (fib_index,
31                                       pfx,
32                                       FIB_SOURCE_PLUGIN_HI,
33                                       FIB_ENTRY_FLAG_EXCLUSIVE, &gfd);
34
35   dpo_reset (&gfd);
36
37   return (0);
38 }
39
40 static int
41 gbp_external_subnet_add (u32 fib_index,
42                          const fib_prefix_t * pfx,
43                          u32 sw_if_index, epg_id_t epg)
44 {
45   dpo_id_t gpd = DPO_INVALID;
46
47   gbp_policy_dpo_add_or_lock (fib_proto_to_dpo (pfx->fp_proto),
48                               epg, sw_if_index, &gpd);
49
50   fib_table_entry_special_dpo_update (fib_index,
51                                       pfx,
52                                       FIB_SOURCE_PLUGIN_HI,
53                                       (FIB_ENTRY_FLAG_EXCLUSIVE |
54                                        FIB_ENTRY_FLAG_LOOSE_URPF_EXEMPT),
55                                       &gpd);
56
57   dpo_reset (&gpd);
58
59   return (0);
60 }
61
62 static int
63 gbp_subnet_del (u32 fib_index, const fib_prefix_t * pfx)
64 {
65   fib_table_entry_delete (fib_index, pfx, FIB_SOURCE_PLUGIN_HI);
66
67   return (0);
68 }
69
70 int
71 gbp_subnet_add_del (u32 table_id,
72                     const fib_prefix_t * pfx,
73                     u32 sw_if_index, epg_id_t epg, u8 is_add, u8 is_internal)
74 {
75   u32 fib_index;
76
77   fib_index = fib_table_find (pfx->fp_proto, table_id);
78
79   if (~0 == fib_index)
80     return (VNET_API_ERROR_NO_SUCH_FIB);
81
82   if (is_internal && is_add)
83     return (gbp_internal_subnet_add (fib_index, pfx));
84   else if (!is_internal && is_add)
85     return (gbp_external_subnet_add (fib_index, pfx, sw_if_index, epg));
86
87   return (gbp_subnet_del (fib_index, pfx));
88 }
89
90 typedef struct gbp_subnet_fib_table_walk_ctx_t_
91 {
92   gbp_subnet_cb_t cb;
93   void *ctx;
94 } gbp_subnet_fib_table_walk_ctx_t;
95
96 static fib_table_walk_rc_t
97 gbp_subnet_fib_table_walk (fib_node_index_t fei, void *arg)
98 {
99   gbp_subnet_fib_table_walk_ctx_t *ctx = arg;
100   const fib_prefix_t *pfx;
101   const dpo_id_t *dpo;
102   u32 table_id;
103
104   pfx = fib_entry_get_prefix (fei);
105   table_id = fib_table_get_table_id (fib_entry_get_fib_index (fei),
106                                      pfx->fp_proto);
107   dpo = fib_entry_contribute_ip_forwarding (fei);
108
109   if (DPO_LOAD_BALANCE == dpo->dpoi_type)
110     {
111       dpo = load_balance_get_bucket (dpo->dpoi_index, 0);
112
113       if (dpo->dpoi_type == gbp_policy_dpo_get_type ())
114         {
115           gbp_policy_dpo_t *gpd;
116
117           gpd = gbp_policy_dpo_get (dpo->dpoi_index);
118
119           /* *INDENT-OFF* */
120           ctx->cb (table_id, pfx,
121                    gpd->gpd_sw_if_index,
122                    gpd->gpd_epg,
123                    0,   // is_internal
124                    ctx->ctx);
125           /* *INDENT-ON* */
126         }
127       else if (dpo->dpoi_type == gbp_fwd_dpo_get_type ())
128         {
129           /* *INDENT-OFF* */
130           ctx->cb (table_id, pfx,
131                    ~0,  // sw_if_index
132                    ~0,  // epg
133                    1,   // is_internal
134                    ctx->ctx);
135           /* *INDENT-ON* */
136         }
137     }
138
139   return (FIB_TABLE_WALK_CONTINUE);
140 }
141
142 void
143 gbp_subnet_walk (gbp_subnet_cb_t cb, void *ctx)
144 {
145   fib_table_t *fib_table;
146
147   gbp_subnet_fib_table_walk_ctx_t wctx = {
148     .cb = cb,
149     .ctx = ctx,
150   };
151
152   /* *INDENT-OFF* */
153   pool_foreach (fib_table, ip4_main.fibs,
154   ({
155     fib_table_walk(fib_table->ft_index,
156                    FIB_PROTOCOL_IP4,
157                    gbp_subnet_fib_table_walk,
158                    &wctx);
159   }));
160   pool_foreach (fib_table, ip6_main.fibs,
161   ({
162     fib_table_walk(fib_table->ft_index,
163                    FIB_PROTOCOL_IP6,
164                    gbp_subnet_fib_table_walk,
165                    &wctx);
166   }));
167   /* *INDENT-ON* */
168 }
169
170 /*
171  * fd.io coding-style-patch-verification: ON
172  *
173  * Local Variables:
174  * eval: (c-set-style "gnu")
175  * End:
176  */