/* helper_flags no redistribution */ 0);
}
-void
-vnet_hw_interface_set_mtu (vnet_main_t * vnm, u32 hw_if_index, u32 mtu)
-{
- vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
-
- if (hi->max_packet_bytes != mtu)
- {
- u16 l3_pad = hi->max_packet_bytes - hi->max_l3_packet_bytes[VLIB_TX];
- hi->max_packet_bytes = mtu;
- hi->max_l3_packet_bytes[VLIB_TX] =
- hi->max_l3_packet_bytes[VLIB_RX] = mtu - l3_pad;
- ethernet_set_flags (vnm, hw_if_index, ETHERNET_INTERFACE_FLAG_MTU);
- adj_mtu_update (hw_if_index);
- }
-}
-
static void
unserialize_vnet_hw_interface_set_flags (serialize_main_t * m, va_list * va)
{
pool_put (im->sw_interfaces, sw);
}
+static clib_error_t *
+call_sw_interface_mtu_change_callbacks (vnet_main_t * vnm, u32 sw_if_index)
+{
+ return call_elf_section_interface_callbacks
+ (vnm, sw_if_index, 0, vnm->sw_interface_mtu_change_functions);
+}
+
+void
+vnet_sw_interface_set_mtu (vnet_main_t * vnm, u32 sw_if_index, u32 mtu)
+{
+ vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
+
+ if (si->mtu[VNET_MTU_L3] != mtu)
+ {
+ si->mtu[VNET_MTU_L3] = mtu;
+ call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
+ }
+}
+
+void
+vnet_sw_interface_set_protocol_mtu (vnet_main_t * vnm, u32 sw_if_index,
+ u32 mtu[])
+{
+ vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
+ bool changed = false;
+ int i;
+
+ for (i = 0; i < VNET_N_MTU; i++)
+ {
+ if (si->mtu[i] != mtu[i])
+ {
+ si->mtu[i] = mtu[i];
+ changed = true;
+ }
+ }
+ /* Notify interested parties */
+ if (changed)
+ call_sw_interface_mtu_change_callbacks (vnm, sw_if_index);
+}
+
+void
+vnet_sw_interface_ip_directed_broadcast (vnet_main_t * vnm,
+ u32 sw_if_index, u8 enable)
+{
+ vnet_sw_interface_t *si;
+
+ si = vnet_get_sw_interface (vnm, sw_if_index);
+
+ if (enable)
+ si->flags |= VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+ else
+ si->flags &= ~VNET_SW_INTERFACE_FLAG_DIRECTED_BCAST;
+
+ ip4_directed_broadcast (sw_if_index, enable);
+}
+
+/*
+ * Reflect a change in hardware MTU on protocol MTUs
+ */
+static walk_rc_t
+sw_interface_walk_callback (vnet_main_t * vnm, u32 sw_if_index, void *ctx)
+{
+ u32 *link_mtu = ctx;
+ vnet_sw_interface_set_mtu (vnm, sw_if_index, *link_mtu);
+ return WALK_CONTINUE;
+}
+
+void
+vnet_hw_interface_set_mtu (vnet_main_t * vnm, u32 hw_if_index, u32 mtu)
+{
+ vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+
+ if (hi->max_packet_bytes != mtu)
+ {
+ hi->max_packet_bytes = mtu;
+ ethernet_set_flags (vnm, hw_if_index, ETHERNET_INTERFACE_FLAG_MTU);
+ vnet_hw_interface_walk_sw (vnm, hw_if_index, sw_interface_walk_callback,
+ &mtu);
+ }
+}
+
static void
setup_tx_node (vlib_main_t * vm,
u32 node_index, vnet_device_class_t * dev_class)
hw->max_rate_bits_per_sec = 0;
hw->min_packet_bytes = 0;
- hw->per_packet_overhead_bytes = 0;
- hw->max_l3_packet_bytes[VLIB_RX] = ~0;
- hw->max_l3_packet_bytes[VLIB_TX] = ~0;
+ vnet_sw_interface_set_mtu (vnm, hw->sw_if_index, 0);
if (dev_class->tx_function == 0)
goto no_output_nodes; /* No output/tx nodes to create */
u32 id, sw_if_index;
hi = vnet_get_hw_interface (vnm, hw_if_index);
- /* the super first, then the and sub interfaces */
- fn (vnm, hi->sw_if_index, ctx);
+ /* the super first, then the sub interfaces */
+ if (WALK_STOP == fn (vnm, hi->sw_if_index, ctx))
+ return;
/* *INDENT-OFF* */
hash_foreach (id, sw_if_index,
/* *INDENT-ON* */
}
+void
+vnet_hw_interface_walk (vnet_main_t * vnm,
+ vnet_hw_interface_walk_t fn, void *ctx)
+{
+ vnet_interface_main_t *im;
+ vnet_hw_interface_t *hi;
+
+ im = &vnm->interface_main;
+
+ /* *INDENT-OFF* */
+ pool_foreach (hi, im->hw_interfaces,
+ ({
+ if (WALK_STOP == fn(vnm, hi->hw_if_index, ctx))
+ break;
+ }));
+ /* *INDENT-ON* */
+}
+
void
vnet_sw_interface_walk (vnet_main_t * vnm,
vnet_sw_interface_walk_t fn, void *ctx)
vnet_sw_interface_is_p2p (vnet_main_t * vnm, u32 sw_if_index)
{
vnet_sw_interface_t *si = vnet_get_sw_interface (vnm, sw_if_index);
- if (si->type == VNET_SW_INTERFACE_TYPE_P2P)
+ if ((si->type == VNET_SW_INTERFACE_TYPE_P2P) ||
+ (si->type == VNET_SW_INTERFACE_TYPE_PIPE))
return 1;
vnet_hw_interface_t *hw = vnet_get_sup_hw_interface (vnm, sw_if_index);
CLIB_CACHE_LINE_BYTES);
im->sw_if_counter_lock[0] = 1; /* should be no need */
- /*
- * $$$$ add stat segment name(s) if desired
- * set xxx.stat_segment_name = "whatever"...
- */
vec_validate (im->sw_if_counters, VNET_N_SIMPLE_INTERFACE_COUNTER - 1);
- im->sw_if_counters[VNET_INTERFACE_COUNTER_DROP].name = "drops";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_PUNT].name = "punts";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_IP4].name = "ip4";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_IP6].name = "ip6";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_NO_BUF].name = "rx-no-buf";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_MISS].name = "rx-miss";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_RX_ERROR].name = "rx-error";
- im->sw_if_counters[VNET_INTERFACE_COUNTER_TX_ERROR].name = "tx-error";
-
- vec_validate (im->combined_sw_if_counters,
- VNET_N_COMBINED_INTERFACE_COUNTER - 1);
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX].name = "rx";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_UNICAST].name =
- "rx-unicast";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_MULTICAST].name =
- "rx-multicast";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_RX_BROADCAST].name =
- "rx-broadcast";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX].name = "tx";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_UNICAST].name =
- "tx-unicast";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_MULTICAST].name =
- "tx-multicast";
- im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_TX_BROADCAST].name =
- "tx-broadcast";
-
- im->sw_if_counter_lock[0] = 0;
+#define _(E,n,p) \
+ im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n; \
+ im->sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
+ foreach_simple_interface_counter_name
+#undef _
+ vec_validate (im->combined_sw_if_counters,
+ VNET_N_COMBINED_INTERFACE_COUNTER - 1);
+#define _(E,n,p) \
+ im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].name = #n; \
+ im->combined_sw_if_counters[VNET_INTERFACE_COUNTER_##E].stat_segment_name = "/" #p "/" #n;
+ foreach_combined_interface_counter_name
+#undef _
+ im->sw_if_counter_lock[0] = 0;
im->device_class_by_name = hash_create_string ( /* size */ 0,
sizeof (uword));
{
c->index = vec_len (im->device_classes);
hash_set_mem (im->device_class_by_name, c->name, c->index);
+
+ if (c->tx_fn_registrations)
+ {
+ vlib_node_fn_registration_t *fnr = c->tx_fn_registrations;
+ int priority = -1;
+
+ /* to avoid confusion, please remove ".tx_function" statiement
+ from VNET_DEVICE_CLASS() if using function candidates */
+ ASSERT (c->tx_function == 0);
+
+ while (fnr)
+ {
+ if (fnr->priority > priority)
+ {
+ priority = fnr->priority;
+ c->tx_function = fnr->function;
+ }
+ fnr = fnr->next_registration;
+ }
+ }
+
vec_add1 (im->device_classes, c[0]);
c = c->next_class_registration;
}
return (0);
}
+vnet_mtu_t
+vnet_link_to_mtu (vnet_link_t link)
+{
+ switch (link)
+ {
+ case VNET_LINK_IP4:
+ return (VNET_MTU_IP4);
+ case VNET_LINK_IP6:
+ return (VNET_MTU_IP6);
+ case VNET_LINK_MPLS:
+ return (VNET_MTU_MPLS);
+ default:
+ return (VNET_MTU_L3);
+ }
+}
+
u8 *
default_build_rewrite (vnet_main_t * vnm,
u32 sw_if_index,
adj_glean_update_rewrite (ai);
break;
case IP_LOOKUP_NEXT_ARP:
+ case IP_LOOKUP_NEXT_BCAST:
/*
* default rewirte in neighbour adj
*/