ip: Router ID included in flow hash
[vpp.git] / src / vnet / mpls / mpls_features.c
1 /*
2  * mpls_features.c: MPLS input and output features
3  *
4  * Copyright (c) 2016 Cisco and/or its affiliates.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #include <vnet/mpls/mpls.h>
19
20 static u8 *
21 format_mpls_drop_trace (u8 * s, va_list * args)
22 {
23   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
24   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
25
26   s = format (s, "drop");
27   return s;
28 }
29
30 static void
31 mpls_drop_trace (vlib_main_t * vm,
32                  vlib_node_runtime_t * node,
33                  vlib_frame_t * frame)
34 {
35   u32 *from, n_left;
36
37   n_left = frame->n_vectors;
38   from = vlib_frame_vector_args (frame);
39
40   while (n_left >= 1)
41     {
42       vlib_buffer_t *b0;
43       u32 bi0;
44
45       bi0 = from[0];
46
47       b0 = vlib_get_buffer (vm, bi0);
48
49       if (b0->flags & VLIB_BUFFER_IS_TRACED)
50       {
51           vlib_add_trace (vm, node, b0, 0);
52       }
53       from += 1;
54       n_left -= 1;
55     }
56 }
57
58 always_inline uword
59 mpls_terminate (vlib_main_t * vm,
60                 vlib_node_runtime_t * node,
61                 vlib_frame_t * frame,
62                 int error_code)
63 {
64   u32 * buffers = vlib_frame_vector_args (frame);
65   uword n_packets = frame->n_vectors;
66
67   if (node->flags & VLIB_NODE_FLAG_TRACE)
68       mpls_drop_trace (vm, node, frame);
69
70   vlib_error_drop_buffers (vm, node,
71                            buffers,
72                            /* stride */ 1,
73                            n_packets,
74                            /* next */ 0,
75                            mpls_input_node.index,
76                            error_code);
77
78   return n_packets;
79 }
80
81 VLIB_NODE_FN (mpls_punt_node) (vlib_main_t * vm,
82            vlib_node_runtime_t * node,
83            vlib_frame_t * frame)
84 {
85     return (mpls_terminate(vm, node, frame, MPLS_ERROR_PUNT));
86 }
87
88 VLIB_REGISTER_NODE (mpls_punt_node) = {
89   .name = "mpls-punt",
90   .vector_size = sizeof (u32),
91   .format_trace = format_mpls_drop_trace,
92
93   .n_next_nodes = 1,
94   .next_nodes = {
95     [0] = "error-punt",
96   },
97 };
98
99 VLIB_NODE_FN (mpls_drop_node) (vlib_main_t * vm,
100            vlib_node_runtime_t * node,
101            vlib_frame_t * frame)
102 {
103     return (mpls_terminate(vm, node, frame, MPLS_ERROR_DROP));
104 }
105
106 VLIB_REGISTER_NODE (mpls_drop_node) = {
107   .name = "mpls-drop",
108   .vector_size = sizeof (u32),
109   .format_trace = format_mpls_drop_trace,
110
111   .n_next_nodes = 1,
112   .next_nodes = {
113     [0] = "error-drop",
114   },
115 };
116
117 VLIB_NODE_FN (mpls_not_enabled_node) (vlib_main_t * vm,
118                   vlib_node_runtime_t * node,
119                   vlib_frame_t * frame)
120 {
121     return (mpls_terminate(vm, node, frame, MPLS_ERROR_NOT_ENABLED));
122 }
123
124 VLIB_REGISTER_NODE (mpls_not_enabled_node) = {
125   .name = "mpls-not-enabled",
126   .vector_size = sizeof (u32),
127   .format_trace = format_mpls_drop_trace,
128
129   .n_next_nodes = 1,
130   .next_nodes = {
131     [0] = "error-drop",
132   },
133 };
134
135 VNET_FEATURE_ARC_INIT (mpls_input, static) =
136 {
137   .arc_name  = "mpls-input",
138   .start_nodes = VNET_FEATURES ("mpls-input"),
139   .last_in_arc = "mpls-lookup",
140   .arc_index_ptr = &mpls_main.input_feature_arc_index,
141 };
142
143 VNET_FEATURE_INIT (mpls_not_enabled, static) = {
144   .arc_name = "mpls-input",
145   .node_name = "mpls-not-enabled",
146   .runs_before = VNET_FEATURES ("mpls-lookup"),
147 };
148
149 VNET_FEATURE_INIT (mpls_lookup, static) = {
150   .arc_name = "mpls-input",
151   .node_name = "mpls-lookup",
152   .runs_before = VNET_FEATURES (0), /* not before any other features */
153 };
154
155 VNET_FEATURE_ARC_INIT (mpls_output, static) =
156 {
157   .arc_name  = "mpls-output",
158   .start_nodes = VNET_FEATURES ("mpls-output", "mpls-midchain"),
159   .last_in_arc = "interface-output",
160   .arc_index_ptr = &mpls_main.output_feature_arc_index,
161 };
162
163 /* Built-in ip4 tx feature path definition */
164 VNET_FEATURE_INIT (mpls_interface_output, static) = {
165   .arc_name = "mpls-output",
166   .node_name = "interface-output",
167   .runs_before = 0, /* not before any other features */
168 };
169
170 static clib_error_t *
171 mpls_sw_interface_add_del (vnet_main_t * vnm,
172                            u32 sw_if_index,
173                            u32 is_add)
174 {
175   mpls_main_t * mm = &mpls_main;
176
177   vec_validate_init_empty (mm->mpls_enabled_by_sw_if_index, sw_if_index, 0);
178   vec_validate_init_empty (mm->fib_index_by_sw_if_index, sw_if_index, 0);
179
180   vnet_feature_enable_disable ("mpls-input", "mpls-not-enabled", sw_if_index,
181                                is_add, 0, 0);
182
183   return /* no error */ 0;
184 }
185
186 VNET_SW_INTERFACE_ADD_DEL_FUNCTION (mpls_sw_interface_add_del);
187
188