int echo_source_is_set;
/* loopback interface used to get echo source ip */
u32 echo_source_sw_if_index;
+ /* node index of "ip4-arp" node */
+ u32 ip4_arp_idx;
+ /* node index of "ip6-discover-neighbor" node */
+ u32 ip6_ndp_idx;
+ /* node index of "ip4-rewrite" node */
+ u32 ip4_rewrite_idx;
+ /* node index of "ip6-rewrite" node */
+ u32 ip6_rewrite_idx;
+ /* log class */
+ vlib_log_class_t log_class;
} bfd_udp_main_t;
static vlib_node_registration_t bfd_udp4_input_node;
if (ia->address_length <= 31)
{
addr->as_u32 = clib_host_to_net_u32 (x->as_u32);
- /*
- * flip the last bit to get a different address, might be network,
- * we don't care ...
- */
- addr->as_u32 ^= 1;
+ /*
+ * flip the last bit to get a different address, might be network,
+ * we don't care ...
+ */
+ addr->as_u32 ^= 1;
addr->as_u32 = clib_net_to_host_u32 (addr->as_u32);
return 1;
}
}
void
-bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index, int *have_usable_ip4,
- ip4_address_t * ip4, int *have_usable_ip6,
- ip6_address_t * ip6)
+bfd_udp_get_echo_source (int *is_set, u32 * sw_if_index,
+ int *have_usable_ip4, ip4_address_t * ip4,
+ int *have_usable_ip6, ip6_address_t * ip6)
{
if (bfd_udp_main.echo_source_is_set)
{
}
int
-bfd_add_udp4_transport (vlib_main_t * vm, vlib_buffer_t * b,
- const bfd_session_t * bs, int is_echo)
+bfd_add_udp4_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
+ int is_echo)
{
const bfd_udp_session_t *bus = &bs->udp;
const bfd_udp_key_t *key = &bus->key;
+ vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
+ b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
+ vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
+ vnet_buffer (b)->sw_if_index[VLIB_TX] = ~0;
typedef struct
{
ip4_header_t ip4;
}
int
-bfd_add_udp6_transport (vlib_main_t * vm, vlib_buffer_t * b,
- const bfd_session_t * bs, int is_echo)
+bfd_add_udp6_transport (vlib_main_t * vm, u32 bi, const bfd_session_t * bs,
+ int is_echo)
{
const bfd_udp_session_t *bus = &bs->udp;
const bfd_udp_key_t *key = &bus->key;
+ vlib_buffer_t *b = vlib_get_buffer (vm, bi);
- b->flags |= VNET_BUFFER_LOCALLY_ORIGINATED;
+ b->flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
vnet_buffer (b)->ip.adj_index[VLIB_RX] = bus->adj_index;
vnet_buffer (b)->ip.adj_index[VLIB_TX] = bus->adj_index;
+ vnet_buffer (b)->sw_if_index[VLIB_RX] = 0;
+ vnet_buffer (b)->sw_if_index[VLIB_TX] = 0;
typedef struct
{
ip6_header_t ip6;
return 1;
}
+static void
+bfd_create_frame_to_next_node (vlib_main_t * vm, u32 bi, u32 next_node)
+{
+ vlib_frame_t *f = vlib_get_frame_to_node (vm, next_node);
+ u32 *to_next = vlib_frame_vector_args (f);
+ to_next[0] = bi;
+ f->n_vectors = 1;
+ vlib_put_frame_to_node (vm, next_node, f);
+}
+
+int
+bfd_udp_calc_next_node (const struct bfd_session_s *bs, u32 * next_node)
+{
+ const bfd_udp_session_t *bus = &bs->udp;
+ ip_adjacency_t *adj = adj_get (bus->adj_index);
+ switch (adj->lookup_next_index)
+ {
+ case IP_LOOKUP_NEXT_ARP:
+ switch (bs->transport)
+ {
+ case BFD_TRANSPORT_UDP4:
+ *next_node = bfd_udp_main.ip4_arp_idx;
+ return 1;
+ case BFD_TRANSPORT_UDP6:
+ *next_node = bfd_udp_main.ip6_ndp_idx;
+ return 1;
+ }
+ break;
+ case IP_LOOKUP_NEXT_REWRITE:
+ switch (bs->transport)
+ {
+ case BFD_TRANSPORT_UDP4:
+ *next_node = bfd_udp_main.ip4_rewrite_idx;
+ return 1;
+ case BFD_TRANSPORT_UDP6:
+ *next_node = bfd_udp_main.ip6_rewrite_idx;
+ return 1;
+ }
+ break;
+ default:
+ /* drop */
+ break;
+ }
+ return 0;
+}
+
+int
+bfd_transport_udp4 (vlib_main_t * vm, u32 bi, const struct bfd_session_s *bs)
+{
+ u32 next_node;
+ int rv = bfd_udp_calc_next_node (bs, &next_node);
+ if (rv)
+ {
+ bfd_create_frame_to_next_node (vm, bi, next_node);
+ }
+ return rv;
+}
+
+int
+bfd_transport_udp6 (vlib_main_t * vm, u32 bi, const struct bfd_session_s *bs)
+{
+ u32 next_node;
+ int rv = bfd_udp_calc_next_node (bs, &next_node);
+ if (rv)
+ {
+ bfd_create_frame_to_next_node (vm, bi, next_node);
+ }
+ return 1;
+}
+
static bfd_session_t *
bfd_lookup_session (bfd_udp_main_t * bum, const bfd_udp_key_t * key)
{
const bfd_session_t *tmp = bfd_lookup_session (bum, key);
if (tmp)
{
- clib_warning ("duplicate bfd-udp session, existing bs_idx=%d",
+ vlib_log_err (bum->log_class,
+ "duplicate bfd-udp session, existing bs_idx=%d",
tmp->bs_idx);
bfd_put_session (bum->bfd_main, bs);
return VNET_API_ERROR_BFD_EEXIST;
bs->bs_idx, key->sw_if_index, format_ip46_address,
&key->local_addr, IP46_TYPE_ANY, format_ip46_address,
&key->peer_addr, IP46_TYPE_ANY);
+ vlib_log_info (bum->log_class, "create BFD session: %U",
+ format_bfd_session, bs);
if (BFD_TRANSPORT_UDP4 == t)
{
bus->adj_index = adj_nbr_add_or_lock (FIB_PROTOCOL_IP4, VNET_LINK_IP4,
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr)
{
+ bfd_udp_main_t *bum = &bfd_udp_main;
vnet_sw_interface_t *sw_if =
vnet_get_sw_interface_safe (bfd_udp_main.vnet_main, sw_if_index);
u8 local_ip_valid = 0;
ip_interface_address_t *ia = NULL;
if (!sw_if)
{
- clib_warning ("got NULL sw_if");
+ vlib_log_err (bum->log_class,
+ "got NULL sw_if when getting interface by index %u",
+ sw_if_index);
return VNET_API_ERROR_INVALID_SW_IF_INDEX;
}
if (ip46_address_is_ip4 (local_addr))
{
if (!ip46_address_is_ip4 (peer_addr))
{
- clib_warning ("IP family mismatch");
+ vlib_log_err (bum->log_class,
+ "IP family mismatch (local is ipv4, peer is ipv6)");
return VNET_API_ERROR_INVALID_ARGUMENT;
}
ip4_main_t *im = &ip4_main;
{
if (ip46_address_is_ip4 (peer_addr))
{
- clib_warning ("IP family mismatch");
+ vlib_log_err (bum->log_class,
+ "IP family mismatch (local is ipv6, peer is ipv4)");
return VNET_API_ERROR_INVALID_ARGUMENT;
}
ip6_main_t *im = &ip6_main;
if (!local_ip_valid)
{
- clib_warning ("address not found on interface");
+ vlib_log_err (bum->log_class,
+ "local address %U not found on interface with index %u",
+ format_ip46_address, local_addr, IP46_TYPE_ANY,
+ sw_if_index);
return VNET_API_ERROR_ADDRESS_NOT_FOUND_FOR_INTERFACE;
}
}
else
{
- clib_warning
- ("BFD session not found (sw_if_index=%u, local=%U, peer=%U",
- sw_if_index, format_ip46_address, local_addr, IP46_TYPE_ANY,
- format_ip46_address, peer_addr, IP46_TYPE_ANY);
+ vlib_log_err (bum->log_class,
+ "BFD session not found, sw_if_index=%u, local=%U, peer=%U",
+ sw_if_index, format_ip46_address, local_addr,
+ IP46_TYPE_ANY, format_ip46_address, peer_addr,
+ IP46_TYPE_ANY);
return VNET_API_ERROR_BFD_ENOENT;
}
}
const ip46_address_t * local_addr,
const ip46_address_t * peer_addr)
{
+ bfd_udp_main_t *bum = &bfd_udp_main;
vnet_api_error_t rv =
bfd_udp_validate_api_input (sw_if_index, local_addr, peer_addr);
if (rv)
}
if (detect_mult < 1)
{
- clib_warning ("detect_mult < 1");
+ vlib_log_err (bum->log_class, "detect_mult < 1");
return VNET_API_ERROR_INVALID_ARGUMENT;
}
if (desired_min_tx_usec < 1)
{
- clib_warning ("desired_min_tx_usec < 1");
+ vlib_log_err (bum->log_class, "desired_min_tx_usec < 1");
return VNET_API_ERROR_INVALID_ARGUMENT;
}
return 0;
rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id,
0 /* is not delayed */ );
#else
- clib_warning ("SSL missing, cannot add authenticated BFD session");
+ vlib_log_err (bfd_udp_main.log_class,
+ "SSL missing, cannot add authenticated BFD session");
rv = VNET_API_ERROR_BFD_NOTSUPP;
#endif
if (rv)
}
return bfd_auth_activate (bs, conf_key_id, key_id, is_delayed);
#else
- clib_warning ("SSL missing, cannot activate BFD authentication");
+ vlib_log_err (bfd_udp_main->log_class,
+ "SSL missing, cannot activate BFD authentication");
return VNET_API_ERROR_BFD_NOTSUPP;
#endif
}
typedef enum
{
BFD_UDP_INPUT_NEXT_NORMAL,
- BFD_UDP_INPUT_NEXT_REPLY,
+ BFD_UDP_INPUT_NEXT_REPLY_ARP,
+ BFD_UDP_INPUT_NEXT_REPLY_REWRITE,
BFD_UDP_INPUT_N_NEXT,
} bfd_udp_input_next_t;
udp_header_t ** udp)
{
/* sanity check first */
- const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+ const i32 start = vnet_buffer (b)->l3_hdr_offset;
if (start < 0 && start < sizeof (b->pre_data))
{
BFD_ERR ("Start of ip header is before pre_data, ignoring");
udp_header_t ** udp)
{
/* sanity check first */
- const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+ const i32 start = vnet_buffer (b)->l3_hdr_offset;
if (start < 0 && start < sizeof (b->pre_data))
{
BFD_ERR ("Start of ip header is before pre_data, ignoring");
const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
if (bfd_pkt_get_poll (pkt))
{
- bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main,
- bs);
+ b0->current_data = 0;
+ b0->current_length = 0;
+ memset (vnet_buffer (b0), 0, sizeof (*vnet_buffer (b0)));
+ bfd_init_final_control_frame (vm, b0, bfd_udp_main.bfd_main, bs,
+ 0);
if (is_ipv6)
{
vlib_node_increment_counter (vm, bfd_udp6_input_node.index,
vlib_node_increment_counter (vm, bfd_udp4_input_node.index,
b0->error, 1);
}
- next0 = BFD_UDP_INPUT_NEXT_REPLY;
+ const bfd_udp_session_t *bus = &bs->udp;
+ ip_adjacency_t *adj = adj_get (bus->adj_index);
+ switch (adj->lookup_next_index)
+ {
+ case IP_LOOKUP_NEXT_ARP:
+ next0 = BFD_UDP_INPUT_NEXT_REPLY_ARP;
+ break;
+ case IP_LOOKUP_NEXT_REWRITE:
+ next0 = BFD_UDP_INPUT_NEXT_REPLY_REWRITE;
+ break;
+ default:
+ /* drop */
+ break;
+ }
}
}
vlib_set_next_frame_buffer (vm, rt, next0, bi0);
.next_nodes =
{
[BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
- [BFD_UDP_INPUT_NEXT_REPLY] = "ip4-lookup",
+ [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
+ [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
},
};
/* *INDENT-ON* */
.next_nodes =
{
[BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
- [BFD_UDP_INPUT_NEXT_REPLY] = "ip6-lookup",
+ [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
+ [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
},
};
/* *INDENT-ON* */
vlib_node_increment_counter (vm, bfd_udp_echo4_input_node.index,
b0->error, 1);
}
- next0 = BFD_UDP_INPUT_NEXT_REPLY;
+ next0 = BFD_UDP_INPUT_NEXT_REPLY_REWRITE;
}
vlib_set_next_frame_buffer (vm, rt, next0, bi0);
.next_nodes =
{
[BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
- [BFD_UDP_INPUT_NEXT_REPLY] = "ip4-lookup",
+ [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip4-arp",
+ [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip4-lookup",
},
};
/* *INDENT-ON* */
.next_nodes =
{
[BFD_UDP_INPUT_NEXT_NORMAL] = "error-drop",
- [BFD_UDP_INPUT_NEXT_REPLY] = "ip6-lookup",
+ [BFD_UDP_INPUT_NEXT_REPLY_ARP] = "ip6-discover-neighbor",
+ [BFD_UDP_INPUT_NEXT_REPLY_REWRITE] = "ip6-lookup",
},
};
/* *INDENT-ON* */
static clib_error_t *
-bfd_sw_interface_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
+bfd_udp_sw_if_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_create)
{
- // vnet_hw_interface_t *hi = vnet_get_sup_hw_interface (vnm, sw_if_index);
- if (!(flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP))
- {
- /* TODO */
- }
- return 0;
-}
-
-VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (bfd_sw_interface_up_down);
-
-static clib_error_t *
-bfd_hw_interface_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
-{
- if (flags & VNET_HW_INTERFACE_FLAG_LINK_UP)
- {
- /* TODO */
- }
+ bfd_session_t **to_be_freed = NULL;
+ bfd_udp_main_t *bum = &bfd_udp_main;
+ BFD_DBG ("sw_if_add_del called, sw_if_index=%u, is_create=%u", sw_if_index,
+ is_create);
+ if (!is_create)
+ {
+ bfd_session_t *bs;
+ pool_foreach (bs, bfd_udp_main.bfd_main->sessions,
+ {
+ if (bs->transport != BFD_TRANSPORT_UDP4 &&
+ bs->transport != BFD_TRANSPORT_UDP6)
+ {
+ continue;}
+ if (bs->udp.key.sw_if_index != sw_if_index)
+ {
+ continue;}
+ vec_add1 (to_be_freed, bs);}
+ );
+ }
+ bfd_session_t **bs;
+ vec_foreach (bs, to_be_freed)
+ {
+ vlib_log_notice (bum->log_class,
+ "removal of sw_if_index=%u forces removal of bfd session "
+ "with bs_idx=%u", sw_if_index, (*bs)->bs_idx);
+ bfd_session_set_flags (*bs, 0);
+ bfd_udp_del_session_internal (*bs);
+ }
return 0;
}
-VNET_HW_INTERFACE_LINK_UP_DOWN_FUNCTION (bfd_hw_interface_up_down);
+VNET_SW_INTERFACE_ADD_DEL_FUNCTION (bfd_udp_sw_if_add_del);
/*
* setup function
bfd_udp_echo4_input_node.index, 1);
udp_register_dst_port (vm, UDP_DST_PORT_bfd_echo6,
bfd_udp_echo6_input_node.index, 0);
+ vlib_node_t *node = vlib_get_node_by_name (vm, (u8 *) "ip4-arp");
+ ASSERT (node);
+ bfd_udp_main.ip4_arp_idx = node->index;
+ node = vlib_get_node_by_name (vm, (u8 *) "ip6-discover-neighbor");
+ ASSERT (node);
+ bfd_udp_main.ip6_ndp_idx = node->index;
+ node = vlib_get_node_by_name (vm, (u8 *) "ip4-rewrite");
+ ASSERT (node);
+ bfd_udp_main.ip4_rewrite_idx = node->index;
+ node = vlib_get_node_by_name (vm, (u8 *) "ip6-rewrite");
+ ASSERT (node);
+ bfd_udp_main.ip6_rewrite_idx = node->index;
+
+ bfd_udp_main.log_class = vlib_log_register_class ("bfd", "udp");
+ vlib_log_debug (bfd_udp_main.log_class, "initialized");
return 0;
}