Line data Source code
1 : /* 2 : * l2_bvi.c : layer 2 Bridged Virtual Interface 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 : #include <vnet/l2/l2_bvi.h> 19 : 20 : /** 21 : * send packets to l2-input. 22 : */ 23 2302 : VNET_DEVICE_CLASS_TX_FN (bvi_device_class) (vlib_main_t * vm, 24 : vlib_node_runtime_t * node, 25 : vlib_frame_t * frame) 26 : { 27 : u32 sw_if_indices[VLIB_FRAME_SIZE], *sw_if_index; 28 : vlib_buffer_t *bufs[VLIB_FRAME_SIZE], **b; 29 : u16 nexts[VLIB_FRAME_SIZE]; 30 : u32 n_left, *from; 31 : 32 2 : n_left = frame->n_vectors; 33 2 : from = vlib_frame_vector_args (frame); 34 : 35 2 : vlib_get_buffers (vm, from, bufs, n_left); 36 : 37 2 : b = bufs; 38 2 : sw_if_index = sw_if_indices; 39 : 40 : /* It's all going to l2-input */ 41 2 : clib_memset_u16 (nexts, 0, VLIB_FRAME_SIZE); 42 : 43 : /* 44 : * For each packet: 45 : * - fixup the L2 length of the packet 46 : * - set the RX interface (which the bridge will use) to the 47 : * TX interface (which routing has chosen) 48 : * - Set the TX interface to the special ID so the DP knows this is a BVI 49 : * Don't counts packets and bytes, that's done in the bviX-output node 50 : */ 51 66 : while (n_left >= 4) 52 : { 53 : /* Prefetch next iteration. */ 54 64 : if (PREDICT_TRUE (n_left >= 8)) 55 : { 56 : /* LOAD pre-fetch since meta and packet data is read */ 57 63 : vlib_prefetch_buffer_header (b[4], LOAD); 58 63 : vlib_prefetch_buffer_header (b[5], LOAD); 59 63 : vlib_prefetch_buffer_header (b[6], LOAD); 60 63 : vlib_prefetch_buffer_header (b[7], LOAD); 61 : 62 63 : vlib_prefetch_buffer_data (b[4], LOAD); 63 63 : vlib_prefetch_buffer_data (b[5], LOAD); 64 63 : vlib_prefetch_buffer_data (b[6], LOAD); 65 63 : vlib_prefetch_buffer_data (b[7], LOAD); 66 : } 67 : 68 64 : vnet_update_l2_len (b[0]); 69 64 : vnet_update_l2_len (b[1]); 70 64 : vnet_update_l2_len (b[2]); 71 64 : vnet_update_l2_len (b[3]); 72 : 73 64 : sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX]; 74 64 : sw_if_index[1] = vnet_buffer (b[1])->sw_if_index[VLIB_TX]; 75 64 : sw_if_index[2] = vnet_buffer (b[2])->sw_if_index[VLIB_TX]; 76 64 : sw_if_index[3] = vnet_buffer (b[3])->sw_if_index[VLIB_TX]; 77 : 78 64 : vnet_buffer (b[0])->sw_if_index[VLIB_TX] = L2INPUT_BVI; 79 64 : vnet_buffer (b[1])->sw_if_index[VLIB_TX] = L2INPUT_BVI; 80 64 : vnet_buffer (b[2])->sw_if_index[VLIB_TX] = L2INPUT_BVI; 81 64 : vnet_buffer (b[3])->sw_if_index[VLIB_TX] = L2INPUT_BVI; 82 : 83 64 : vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index[0]; 84 64 : vnet_buffer (b[1])->sw_if_index[VLIB_RX] = sw_if_index[1]; 85 64 : vnet_buffer (b[2])->sw_if_index[VLIB_RX] = sw_if_index[2]; 86 64 : vnet_buffer (b[3])->sw_if_index[VLIB_RX] = sw_if_index[3]; 87 : 88 64 : b += 4; 89 64 : n_left -= 4; 90 64 : sw_if_index += 4; 91 : } 92 3 : while (n_left) 93 : { 94 1 : sw_if_index[0] = vnet_buffer (b[0])->sw_if_index[VLIB_TX]; 95 1 : vnet_buffer (b[0])->sw_if_index[VLIB_TX] = L2INPUT_BVI; 96 1 : vnet_buffer (b[0])->sw_if_index[VLIB_RX] = sw_if_index[0]; 97 : 98 1 : vnet_update_l2_len (b[0]); 99 : 100 1 : b += 1; 101 1 : n_left -= 1; 102 1 : sw_if_index += 1; 103 : } 104 : 105 2 : vlib_buffer_enqueue_to_next (vm, node, from, nexts, frame->n_vectors); 106 : 107 2 : return frame->n_vectors; 108 : } 109 : 110 : /* 111 : * fd.io coding-style-patch-verification: ON 112 : * 113 : * Local Variables: 114 : * eval: (c-set-style "gnu") 115 : * End: 116 : */