+int
+af_packet_enable_disable_qdisc_bypass (u32 sw_if_index, u8 enable_disable)
+{
+ af_packet_main_t *apm = &af_packet_main;
+ af_packet_if_t *apif;
+ vnet_main_t *vnm = vnet_get_main ();
+ vnet_hw_interface_t *hw;
+ u32 i;
+
+ hw = vnet_get_sup_hw_interface_api_visible_or_null (vnm, sw_if_index);
+
+ if (hw->dev_class_index != af_packet_device_class.index)
+ return VNET_API_ERROR_INVALID_INTERFACE;
+
+ apif = pool_elt_at_index (apm->interfaces, hw->dev_instance);
+
+#if defined(PACKET_QDISC_BYPASS)
+ vec_foreach_index (i, apif->fds)
+ {
+ if (enable_disable)
+ {
+ int opt = 1;
+
+ /* Introduced with Linux 3.14 so the ifdef should eventually be
+ * removed */
+ if (setsockopt (apif->fds[i], SOL_PACKET, PACKET_QDISC_BYPASS, &opt,
+ sizeof (opt)) < 0)
+ {
+ vlib_log_err (apm->log_class,
+ "Failed to enable qdisc bypass error "
+ "handling option: %s (errno %d)",
+ strerror (errno), errno);
+ }
+ apif->is_qdisc_bypass_enabled = 1;
+ }
+ else
+ {
+ int opt = 0;
+ if (setsockopt (apif->fds[i], SOL_PACKET, PACKET_QDISC_BYPASS, &opt,
+ sizeof (opt)) < 0)
+ {
+ vlib_log_err (apm->log_class,
+ "Failed to disable qdisc bypass error "
+ "handling option: %s (errno %d)",
+ strerror (errno), errno);
+ }
+ apif->is_qdisc_bypass_enabled = 0;
+ }
+ }
+
+#endif
+ return 0;
+}
+