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 : #include <vnet/mpls/mpls_types.h>
17 : #include <vnet/dpo/drop_dpo.h>
18 :
19 : #include <vnet/fib/fib_table.h>
20 : #include <vnet/fib/fib_entry.h>
21 : #include <vnet/fib/fib_entry_src.h>
22 : #include <vnet/fib/mpls_fib.h>
23 :
24 : /**
25 : * Source initialisation Function
26 : */
27 : static void
28 140 : fib_entry_src_mpls_init (fib_entry_src_t *src)
29 : {
30 : mpls_eos_bit_t eos;
31 :
32 140 : src->fes_flags = FIB_ENTRY_SRC_FLAG_NONE;
33 140 : src->u.mpls.fesm_label = MPLS_LABEL_INVALID;
34 :
35 420 : FOR_EACH_MPLS_EOS_BIT(eos)
36 : {
37 280 : src->u.mpls.fesm_lfes[eos] = FIB_NODE_INDEX_INVALID;
38 : }
39 140 : }
40 :
41 : /**
42 : * Source deinitialisation Function
43 : */
44 : static void
45 140 : fib_entry_src_mpls_deinit (fib_entry_src_t *src)
46 : {
47 140 : }
48 :
49 : static void
50 140 : fib_entry_src_mpls_remove (fib_entry_src_t *src)
51 : {
52 140 : src->fes_pl = FIB_NODE_INDEX_INVALID;
53 140 : src->u.mpls.fesm_label = MPLS_LABEL_INVALID;
54 140 : }
55 :
56 : static void
57 140 : fib_entry_src_mpls_add (fib_entry_src_t *src,
58 : const fib_entry_t *entry,
59 : fib_entry_flag_t flags,
60 : dpo_proto_t proto,
61 : const dpo_id_t *dpo)
62 : {
63 140 : src->fes_pl =
64 140 : fib_path_list_create_special(proto,
65 : FIB_PATH_LIST_FLAG_DROP,
66 : drop_dpo_get(proto));
67 140 : }
68 :
69 : static void
70 281 : fib_entry_src_mpls_set_data (fib_entry_src_t *src,
71 : const fib_entry_t *entry,
72 : const void *data)
73 : {
74 : fib_protocol_t payload_proto;
75 : fib_node_index_t fei;
76 : mpls_label_t label;
77 : mpls_eos_bit_t eos;
78 :
79 : /*
80 : * post MPLS table alloc and the possible rea-alloc of fib entrys
81 : * the entry pointer will no longer be valid. so save its index
82 : */
83 281 : payload_proto = entry->fe_prefix.fp_proto;
84 281 : fei = fib_entry_get_index(entry);
85 281 : label = *(mpls_label_t*)data;
86 :
87 281 : if (MPLS_LABEL_INVALID == label)
88 : {
89 : /*
90 : * removing the local label
91 : */
92 420 : FOR_EACH_MPLS_EOS_BIT(eos)
93 : {
94 280 : fib_table_entry_delete_index(src->u.mpls.fesm_lfes[eos],
95 : FIB_SOURCE_SPECIAL);
96 : }
97 140 : fib_table_unlock(MPLS_FIB_DEFAULT_TABLE_ID,
98 : FIB_PROTOCOL_MPLS,
99 : FIB_SOURCE_MPLS);
100 140 : src->u.mpls.fesm_label = label;
101 : }
102 : else
103 : {
104 141 : fib_prefix_t prefix = {
105 : .fp_proto = FIB_PROTOCOL_MPLS,
106 : .fp_label = label,
107 : };
108 : fib_node_index_t fib_index;
109 141 : dpo_id_t dpo = DPO_INVALID;
110 :
111 : /*
112 : * adding a new local label. make sure the MPLS fib exists.
113 : */
114 141 : if (MPLS_LABEL_INVALID == src->u.mpls.fesm_label)
115 : {
116 : fib_index =
117 140 : fib_table_find_or_create_and_lock(FIB_PROTOCOL_MPLS,
118 : MPLS_FIB_DEFAULT_TABLE_ID,
119 : FIB_SOURCE_MPLS);
120 : }
121 : else
122 : {
123 1 : fib_index = mpls_fib_index_from_table_id(MPLS_FIB_DEFAULT_TABLE_ID);
124 :
125 : /*
126 : * if this is a change in label, remove the old one first
127 : */
128 1 : if (src->u.mpls.fesm_label != label)
129 : {
130 3 : FOR_EACH_MPLS_EOS_BIT(eos)
131 : {
132 2 : ASSERT(FIB_NODE_INDEX_INVALID != src->u.mpls.fesm_lfes[eos]);
133 2 : fib_table_entry_delete_index(src->u.mpls.fesm_lfes[eos],
134 : FIB_SOURCE_SPECIAL);
135 : }
136 : }
137 : }
138 :
139 141 : src->u.mpls.fesm_label = label;
140 :
141 423 : FOR_EACH_MPLS_EOS_BIT(eos)
142 : {
143 282 : prefix.fp_eos = eos;
144 282 : prefix.fp_payload_proto = fib_proto_to_dpo(payload_proto);
145 :
146 282 : fib_entry_contribute_forwarding(fei,
147 : (eos ?
148 : FIB_FORW_CHAIN_TYPE_MPLS_EOS :
149 : FIB_FORW_CHAIN_TYPE_MPLS_NON_EOS),
150 : &dpo);
151 282 : src->u.mpls.fesm_lfes[eos] =
152 282 : fib_table_entry_special_dpo_add(fib_index,
153 : &prefix,
154 : FIB_SOURCE_SPECIAL,
155 : FIB_ENTRY_FLAG_EXCLUSIVE,
156 : &dpo);
157 282 : dpo_reset(&dpo);
158 : }
159 : }
160 281 : }
161 :
162 : static const void *
163 140 : fib_entry_src_mpls_get_data (fib_entry_src_t *src,
164 : const fib_entry_t *entry)
165 : {
166 140 : return (&(src->u.mpls.fesm_label));
167 : }
168 :
169 : static u8*
170 67 : fib_entry_src_mpls_format (fib_entry_src_t *src,
171 : u8* s)
172 : {
173 67 : return (format(s, " local-label:%d", src->u.mpls.fesm_label));
174 : }
175 :
176 : const static fib_entry_src_vft_t mpls_src_vft = {
177 : .fesv_init = fib_entry_src_mpls_init,
178 : .fesv_deinit = fib_entry_src_mpls_deinit,
179 : .fesv_add = fib_entry_src_mpls_add,
180 : .fesv_remove = fib_entry_src_mpls_remove,
181 : .fesv_format = fib_entry_src_mpls_format,
182 : .fesv_set_data = fib_entry_src_mpls_set_data,
183 : .fesv_get_data = fib_entry_src_mpls_get_data,
184 : /*
185 : * .fesv_fwd_update = fib_entry_src_mpls_fwd_update,
186 : * When the forwarding for the IP entry is updated, any MPLS chains
187 : * it has created are also updated. Since the MPLS entry will have already
188 : * installed that chain/load-balance there is no need to update the netry
189 : * FIXME: later: propagate any walk to the children of the MPLS entry. for SR
190 : */
191 : };
192 :
193 : void
194 559 : fib_entry_src_mpls_register (void)
195 : {
196 559 : fib_entry_src_behaviour_register(FIB_SOURCE_BH_MPLS, &mpls_src_vft);
197 559 : }
|