diff options
Diffstat (limited to 'vnet/vnet/gre/gre.c')
-rw-r--r-- | vnet/vnet/gre/gre.c | 209 |
1 files changed, 159 insertions, 50 deletions
diff --git a/vnet/vnet/gre/gre.c b/vnet/vnet/gre/gre.c index 9f8adc79ff0..0028118df94 100644 --- a/vnet/vnet/gre/gre.c +++ b/vnet/vnet/gre/gre.c @@ -47,11 +47,11 @@ u8 * format_gre_tx_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *); CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); gre_tx_trace_t * t = va_arg (*args, gre_tx_trace_t *); - + s = format (s, "GRE: tunnel %d len %d src %U dst %U", - t->tunnel_id, clib_net_to_host_u16 (t->length), - format_ip4_address, &t->src.as_u8, - format_ip4_address, &t->dst.as_u8); + t->tunnel_id, clib_net_to_host_u16 (t->length), + format_ip4_address, &t->src.as_u8, + format_ip4_address, &t->dst.as_u8); return s; } @@ -158,7 +158,7 @@ unformat_gre_header (unformat_input_t * input, va_list * args) vec_add2 (*result, p, n_bytes); clib_memcpy (p, h, n_bytes); } - + return 1; } @@ -198,15 +198,15 @@ static uword gre_set_rewrite (vnet_main_t * vnm, h->ip4.ttl = 64; h->ip4.protocol = IP_PROTOCOL_GRE; h->gre.protocol = clib_host_to_net_u16 (protocol); - + return sizeof (h[0]); -#endif +#endif } static uword gre_interface_tx (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame) + vlib_node_runtime_t * node, + vlib_frame_t * frame) { gre_main_t * gm = &gre_main; u32 next_index; @@ -218,71 +218,140 @@ gre_interface_tx (vlib_main_t * vm, from = vlib_frame_vector_args (frame); /* Number of buffers / pkts */ - n_left_from = frame->n_vectors; + n_left_from = frame->n_vectors; /* Speculatively send the first buffer to the last disposition we used */ next_index = node->cached_next_index; - + while (n_left_from > 0) { /* set up to enqueue to our disposition with index = next_index */ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); - /* + /* * FIXME DUAL LOOP */ while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, adj_index0, next0; + u32 bi0, adj_index0, next0; const ip_adjacency_t * adj0; - const dpo_id_t *dpo0; - ip4_header_t * ip0; - vlib_buffer_t * b0; - - bi0 = from[0]; - to_next[0] = bi0; - from += 1; - to_next += 1; - n_left_from -= 1; - n_left_to_next -= 1; - - b0 = vlib_get_buffer(vm, bi0); - ip0 = vlib_buffer_get_current (b0); - - /* Fixup the checksum and len fields in the LISP tunnel encap - * that was applied at the midchain node */ - ip0->length = - clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); - ip0->checksum = ip4_header_checksum (ip0); - - /* Follow the DPO on which the midchain is stacked */ - adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; + const dpo_id_t *dpo0; + ip4_header_t * ip0; + vlib_buffer_t * b0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer(vm, bi0); + ip0 = vlib_buffer_get_current (b0); + + /* Fixup the checksum and len fields in the GRE tunnel encap + * that was applied at the midchain node */ + ip0->length = + clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)); + ip0->checksum = ip4_header_checksum (ip0); + + /* Follow the DPO on which the midchain is stacked */ + adj_index0 = vnet_buffer(b0)->ip.adj_index[VLIB_TX]; adj0 = adj_get(adj_index0); - dpo0 = &adj0->sub_type.midchain.next_dpo; - next0 = dpo0->dpoi_next_node; - vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; - - if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) - { - gre_tx_trace_t *tr = vlib_add_trace (vm, node, - b0, sizeof (*tr)); - tr->tunnel_id = t - gm->tunnels; - tr->length = ip0->length; - tr->src.as_u32 = ip0->src_address.as_u32; - tr->dst.as_u32 = ip0->dst_address.as_u32; - } + dpo0 = &adj0->sub_type.midchain.next_dpo; + next0 = dpo0->dpoi_next_node; + vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpo0->dpoi_index; + + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_tx_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->tunnel_id = t - gm->tunnels; + tr->length = ip0->length; + tr->src.as_u32 = ip0->src_address.as_u32; + tr->dst.as_u32 = ip0->dst_address.as_u32; + } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, n_left_to_next, bi0, next0); } - + + vlib_put_next_frame (vm, node, next_index, n_left_to_next); + } + + vlib_node_increment_counter (vm, gre_input_node.index, + GRE_ERROR_PKTS_ENCAP, frame->n_vectors); + + return frame->n_vectors; +} + +static uword +gre_l2_interface_tx (vlib_main_t * vm, + vlib_node_runtime_t * node, + vlib_frame_t * frame) +{ + gre_main_t * gm = &gre_main; + u32 next_index; + u32 * from, * to_next, n_left_from, n_left_to_next; + vnet_interface_output_runtime_t * rd = (void *) node->runtime_data; + const gre_tunnel_t *gt = pool_elt_at_index (gm->tunnels, rd->dev_instance); + + /* Vector of buffer / pkt indices we're supposed to process */ + from = vlib_frame_vector_args (frame); + + /* Number of buffers / pkts */ + n_left_from = frame->n_vectors; + + /* Speculatively send the first buffer to the last disposition we used */ + next_index = node->cached_next_index; + + while (n_left_from > 0) + { + /* set up to enqueue to our disposition with index = next_index */ + vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next); + + /* + * FIXME DUAL LOOP + */ + + while (n_left_from > 0 && n_left_to_next > 0) + { + vlib_buffer_t * b0; + u32 bi0; + + bi0 = from[0]; + to_next[0] = bi0; + from += 1; + to_next += 1; + n_left_from -= 1; + n_left_to_next -= 1; + + b0 = vlib_get_buffer(vm, bi0); + + vnet_buffer(b0)->ip.adj_index[VLIB_TX] = gt->adj_index[FIB_LINK_ETHERNET]; + + if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) + { + gre_tx_trace_t *tr = vlib_add_trace (vm, node, + b0, sizeof (*tr)); + tr->tunnel_id = gt - gm->tunnels; + tr->length = vlib_buffer_length_in_chain (vm, b0); + tr->src.as_u32 = gt->tunnel_src.as_u32; + tr->dst.as_u32 = gt->tunnel_src.as_u32; + } + + vlib_validate_buffer_enqueue_x1 (vm, node, next_index, + to_next, n_left_to_next, + bi0, gt->l2_tx_arc); + } + vlib_put_next_frame (vm, node, next_index, n_left_to_next); } vlib_node_increment_counter (vm, gre_input_node.index, - GRE_ERROR_PKTS_ENCAP, frame->n_vectors); + GRE_ERROR_PKTS_ENCAP, frame->n_vectors); return frame->n_vectors; } @@ -290,11 +359,27 @@ gre_interface_tx (vlib_main_t * vm, static clib_error_t * gre_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) { + gre_main_t * gm = &gre_main; + vnet_hw_interface_t * hi; + gre_tunnel_t *t; + u32 ti; + + hi = vnet_get_hw_interface (vnm, hw_if_index); + ti = gm->tunnel_index_by_sw_if_index[hi->sw_if_index]; + + if (~0 == ti) + /* not one of ours */ + return (NULL); + + t = pool_elt_at_index(gm->tunnels, ti); + if (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) vnet_hw_interface_set_flags (vnm, hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); else vnet_hw_interface_set_flags (vnm, hw_if_index, 0 /* down */); + gre_tunnel_stack(t); + return /* no error */ 0; } @@ -313,6 +398,15 @@ static u8 * format_gre_device (u8 * s, va_list * args) return s; } +static u8 * format_gre_l2_device (u8 * s, va_list * args) +{ + u32 dev_instance = va_arg (*args, u32); + CLIB_UNUSED (int verbose) = va_arg (*args, int); + + s = format (s, "GRE L2-tunnel: id %d\n", dev_instance); + return s; +} + VNET_DEVICE_CLASS (gre_device_class) = { .name = "GRE tunnel device", .format_device_name = format_gre_tunnel_name, @@ -328,6 +422,21 @@ VNET_DEVICE_CLASS (gre_device_class) = { VLIB_DEVICE_TX_FUNCTION_MULTIARCH (gre_device_class, gre_interface_tx) +VNET_DEVICE_CLASS (gre_l2_device_class) = { + .name = "GRE L2 tunnel device", + .format_device_name = format_gre_tunnel_name, + .format_device = format_gre_l2_device, + .format_tx_trace = format_gre_tx_trace, + .tx_function = gre_l2_interface_tx, + .admin_up_down_function = gre_interface_admin_up_down, +#ifdef SOON + .clear counter = 0; +#endif +}; + +VLIB_DEVICE_TX_FUNCTION_MULTIARCH (gre_l2_device_class, + gre_l2_interface_tx) + VNET_HW_INTERFACE_CLASS (gre_hw_interface_class) = { .name = "GRE", |