udp: fix csum computation when offload disabled
[vpp.git] / src / vnet / l2 / l2_vtr.h
1 /*
2  * l2_vtr.h : layer 2 vlan tag rewrite processing
3  *
4  * Copyright (c) 2013 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 #ifndef included_vnet_l2_vtr_h
19 #define included_vnet_l2_vtr_h
20
21 #include <vlib/vlib.h>
22 #include <vnet/vnet.h>
23 #include <vnet/ethernet/ethernet.h>
24 #include <vnet/ethernet/packet.h>
25 #include <vnet/l2/l2_vtr.h>
26
27 /* VTR config options for API and CLI support */
28 typedef enum
29 {
30   L2_VTR_DISABLED,
31   L2_VTR_PUSH_1,
32   L2_VTR_PUSH_2,
33   L2_VTR_POP_1,
34   L2_VTR_POP_2,
35   L2_VTR_TRANSLATE_1_1,
36   L2_VTR_TRANSLATE_1_2,
37   L2_VTR_TRANSLATE_2_1,
38   L2_VTR_TRANSLATE_2_2
39 } l2_vtr_op_t;
40
41 /**
42  * Per-interface vlan tag rewrite configuration
43  * There will be one instance of this struct for each sw_if_index
44  * for both input vtr and output vtr
45  */
46 typedef struct
47 {
48   union
49   {
50     /*
51      * Up to two vlan tags to push.
52      * if there is only one vlan tag to push, it is in tags[1].
53      */
54     ethernet_vlan_header_tv_t tags[2];
55     u64 raw_tags;
56   };
57
58   union
59   {
60     struct
61     {
62       u8 push_bytes;            /* number of bytes to push for up to 2 vlans (0,4,8) */
63       u8 pop_bytes;             /* number of bytes to pop for up to 2 vlans (0,4,8) */
64     };
65     u16 push_and_pop_bytes;     /* if 0 then the feature is disabled */
66   };
67 } vtr_config_t;
68
69
70 /**
71  * Perform the configured tag rewrite on the packet.
72  * Return 0 if ok, 1 if packet should be dropped (e.g. tried to pop
73  * too many tags)
74  */
75 always_inline u32
76 l2_vtr_process (vlib_buffer_t * b0, vtr_config_t * config)
77 {
78   u64 temp_8;
79   u32 temp_4;
80   u8 *eth;
81
82   eth = vlib_buffer_get_current (b0);
83
84   /* copy the 12B dmac and smac to a temporary location */
85   temp_8 = *((u64 *) eth);
86   temp_4 = *((u32 *) (eth + 8));
87
88   /* adjust for popped tags */
89   eth += config->pop_bytes;
90
91   /* if not enough tags to pop then drop packet */
92   if (PREDICT_FALSE ((vnet_buffer (b0)->l2.l2_len - 12) < config->pop_bytes))
93     {
94       return 1;
95     }
96
97   /* copy the 2 new tags to the start of the packet  */
98   *((u64 *) (eth + 12 - 8)) = config->raw_tags;
99
100   /* TODO: set cos bits */
101
102   /* adjust for pushed tags: */
103   eth -= config->push_bytes;
104
105   /* copy the 12 dmac and smac back to the packet */
106   *((u64 *) eth) = temp_8;
107   *((u32 *) (eth + 8)) = temp_4;
108
109   /* Update l2 parameters */
110   vnet_buffer (b0)->l2.l2_len +=
111     (word) config->push_bytes - (word) config->pop_bytes;
112   vnet_buffer (b0)->l2_hdr_offset -=
113     (word) config->push_bytes - (word) config->pop_bytes;
114
115   /* Update vlan tag count */
116   ethernet_buffer_adjust_vlan_count_by_bytes (b0,
117                                               (word) config->push_bytes -
118                                               (word) config->pop_bytes);
119
120   /* Update packet len */
121   vlib_buffer_advance (b0,
122                        (word) config->pop_bytes - (word) config->push_bytes);
123
124   return 0;
125 }
126
127
128 /*
129  *  Perform the egress pre-vlan tag rewrite EFP Filter check.
130  * The post-vlan tag rewrite check is a separate graph node.
131  *
132  *  This check insures that a packet being output to an interface
133  * (before output vtr is performed) has vlan tags that match those
134  * on a packet received from that interface (after vtr has been performed).
135  * This means verifying that any tags pushed by input vtr are present
136  * on the packet.
137  *
138  *  Return 0 if ok, 1 if packet should be dropped.
139  * This function should be passed the input vtr config for the interface.
140  */
141 always_inline u8
142 l2_efp_filter_process (vlib_buffer_t * b0, vtr_config_t * in_config)
143 {
144   u8 *eth;
145   u64 packet_tags;
146   u64 tag_mask;
147
148   eth = vlib_buffer_get_current (b0);
149
150   /*
151    * If there are 2 tags pushed, they must match config->tags[0] and
152    * config->tags[1].
153    * If there is one tag pushed, it must match config->tag[1].
154    * If there are 0 tags pushed, the check passes.
155    */
156
157   /* mask for two vlan id and ethertypes, no cos bits */
158   tag_mask = clib_net_to_host_u64 (0xFFFF0FFFFFFF0FFF);
159   /* mask for one vlan id and ethertype, no cos bits */
160   tag_mask =
161     (in_config->push_bytes ==
162      4) ? clib_net_to_host_u64 (0xFFFF0FFF) : tag_mask;
163   /* mask for always match */
164   tag_mask = (in_config->push_bytes == 0) ? 0 : tag_mask;
165
166   /*
167    * Read 8B from the packet, getting the proper set of vlan tags
168    * For 0 push bytes, the address doesn't matter since the mask
169    * clears the data to 0.
170    */
171   packet_tags = *((u64 *) (eth + 4 + in_config->push_bytes));
172
173   /* Check if the packet tags match the configured tags */
174   return (packet_tags & tag_mask) != in_config->raw_tags;
175 }
176
177 typedef struct
178 {
179   union
180   {
181     ethernet_pbb_header_t macs_tags;
182     struct
183     {
184       u64 data1;
185       u64 data2;
186       u16 data3;
187       u32 data4;
188     } raw_data;
189   };
190   union
191   {
192     struct
193     {
194       u8 push_bytes;            /* number of bytes to push pbb tags */
195       u8 pop_bytes;             /* number of bytes to pop pbb tags */
196     };
197     u16 push_and_pop_bytes;     /* if 0 then the feature is disabled */
198   };
199 } ptr_config_t;
200
201 always_inline u32
202 l2_pbb_process (vlib_buffer_t * b0, ptr_config_t * config)
203 {
204   u8 *eth = vlib_buffer_get_current (b0);
205
206   if (config->pop_bytes > 0)
207     {
208       ethernet_pbb_header_packed_t *ph = (ethernet_pbb_header_packed_t *) eth;
209
210       // drop packet without PBB header or with wrong I-tag or B-tag
211       if (clib_net_to_host_u16 (ph->priority_dei_id) !=
212           clib_net_to_host_u16 (config->macs_tags.priority_dei_id)
213           || clib_net_to_host_u32 (ph->priority_dei_uca_res_sid) !=
214           clib_net_to_host_u32 (config->macs_tags.priority_dei_uca_res_sid))
215         return 1;
216
217       eth += config->pop_bytes;
218     }
219
220   if (config->push_bytes > 0)
221     {
222       eth -= config->push_bytes;
223       // copy the B-DA (6B), B-SA (6B), B-TAG (4B), I-TAG (6B)
224       *((u64 *) eth) = config->raw_data.data1;
225       *((u64 *) (eth + 8)) = config->raw_data.data2;
226       *((u16 *) (eth + 16)) = config->raw_data.data3;
227       *((u32 *) (eth + 18)) = config->raw_data.data4;
228     }
229
230   /* Update l2_len */
231   vnet_buffer (b0)->l2.l2_len +=
232     (word) config->push_bytes - (word) config->pop_bytes;
233   /* Update packet len */
234   vlib_buffer_advance (b0,
235                        (word) config->pop_bytes - (word) config->push_bytes);
236
237   return 0;
238 }
239
240 u32 l2pbb_configure (vlib_main_t * vlib_main,
241                      vnet_main_t * vnet_main, u32 sw_if_index, u32 vtr_op,
242                      u8 * b_dmac, u8 * b_smac,
243                      u16 b_vlanid, u32 i_sid, u16 vlan_outer_tag);
244
245 /**
246  * Configure vtag tag rewrite on the given interface.
247  * Return 1 if there is an error, 0 if ok
248  */
249 u32 l2vtr_configure (vlib_main_t * vlib_main,
250                      vnet_main_t * vnet_main,
251                      u32 sw_if_index,
252                      u32 vtr_op, u32 push_dot1q, u32 vtr_tag1, u32 vtr_tag2);
253
254 /**
255  * Get vtag tag rewrite on the given interface.
256  * Return 1 if there is an error, 0 if ok
257  */
258 u32 l2vtr_get (vlib_main_t * vlib_main,
259                vnet_main_t * vnet_main,
260                u32 sw_if_index,
261                u32 * vtr_op,
262                u32 * push_dot1q, u32 * vtr_tag1, u32 * vtr_tag2);
263
264 /**
265  * Get pbb tag rewrite on the given interface.
266  * Return 1 if there is an error, 0 if ok
267  */
268 u32 l2pbb_get (vlib_main_t * vlib_main,
269                vnet_main_t * vnet_main,
270                u32 sw_if_index,
271                u32 * vtr_op,
272                u16 * outer_tag,
273                ethernet_header_t * eth_hdr, u16 * b_vlanid, u32 * i_sid);
274
275 #endif /* included_vnet_l2_vtr_h */
276
277
278 /*
279  * fd.io coding-style-patch-verification: ON
280  *
281  * Local Variables:
282  * eval: (c-set-style "gnu")
283  * End:
284  */