+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;
+ log_debug ("set_mtu: interface %U, new mtu %u",
+ format_vnet_sw_if_index_name, vnm, sw_if_index, 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)
+ {
+ log_debug ("set_protocol_mtu: interface %U l3 %u ip4 %u ip6 %u mpls %u",
+ format_vnet_sw_if_index_name, vnm, sw_if_index,
+ mtu[VNET_MTU_L3], mtu[VNET_MTU_IP4], mtu[VNET_MTU_IP6],
+ mtu[VNET_MTU_MPLS]);
+ 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;
+}
+
+clib_error_t *
+vnet_hw_interface_set_max_frame_size (vnet_main_t *vnm, u32 hw_if_index,
+ u32 fs)
+{
+ vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
+ vnet_hw_interface_class_t *hw_if_class =
+ vnet_get_hw_interface_class (vnm, hi->hw_class_index);
+ clib_error_t *err = 0;
+
+ log_debug ("set_max_frame_size: interface %s, max_frame_size %u -> %u",
+ hi->name, hi->max_frame_size, fs);
+
+ if (hw_if_class->set_max_frame_size == 0)
+ return vnet_error (VNET_ERR_UNSUPPORTED,
+ "hw class doesn't support changing Max Frame Size");
+
+ if (hi->max_frame_size != fs)
+ {
+ u32 mtu;
+ if (hw_if_class->set_max_frame_size)
+ if ((err = hw_if_class->set_max_frame_size (vnm, hi, fs)))
+ return err;
+ hi->max_frame_size = fs;
+ mtu = fs - hi->frame_overhead;
+ vnet_hw_interface_walk_sw (vnm, hw_if_index, sw_interface_walk_callback,
+ &mtu);
+ }
+ return 0;
+}
+clib_error_t *
+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);
+ return vnet_hw_interface_set_max_frame_size (vnm, hw_if_index,
+ mtu + hi->frame_overhead);
+}
+