summaryrefslogtreecommitdiffstats
path: root/src/vnet/devices
diff options
context:
space:
mode:
authorMohsin Kazmi <sykazmi@cisco.com>2020-09-01 17:17:44 +0000
committerMohsin Kazmi <sykazmi@cisco.com>2020-09-02 11:50:00 +0000
commit518251bc8a3e67e25a041bf54d6bb01a2233838b (patch)
tree76723810aafe8bc1252ed75f8876e05b6e7546e0 /src/vnet/devices
parent9f1dbd20b30eda4a045fbe86c7a36a80887630e1 (diff)
virtio: add virtio 1.1 api flags
Type: feature Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com> Change-Id: I95d7fc1cc8db5199570c66535f45e867a7cae676
Diffstat (limited to 'src/vnet/devices')
-rw-r--r--src/vnet/devices/virtio/pci.h15
-rw-r--r--src/vnet/devices/virtio/virtio.api44
-rw-r--r--src/vnet/devices/virtio/virtio_api.c61
3 files changed, 119 insertions, 1 deletions
diff --git a/src/vnet/devices/virtio/pci.h b/src/vnet/devices/virtio/pci.h
index f9a58280aae..47c74ab2ec6 100644
--- a/src/vnet/devices/virtio/pci.h
+++ b/src/vnet/devices/virtio/pci.h
@@ -242,6 +242,20 @@ typedef struct _virtio_pci_func
void (*device_debug_config_space) (vlib_main_t * vm, virtio_if_t * vif);
} virtio_pci_func_t;
+#define foreach_virtio_flags \
+ _ (GSO, 0) \
+ _ (CSUM_OFFLOAD, 1) \
+ _ (GRO_COALESCE, 2) \
+ _ (PACKED, 3) \
+ _ (IN_ORDER, 4)
+
+typedef enum
+{
+#define _(a, b) VIRTIO_FLAG_##a = (1 << b),
+ foreach_virtio_flags
+#undef _
+} virtio_flag_t;
+
typedef struct
{
u32 addr;
@@ -253,6 +267,7 @@ typedef struct
u64 features;
u8 gso_enabled;
u8 checksum_offload_enabled;
+ u32 virtio_flags;
clib_error_t *error;
} virtio_pci_create_if_args_t;
diff --git a/src/vnet/devices/virtio/virtio.api b/src/vnet/devices/virtio/virtio.api
index 34f00fad22c..143d25b73ab 100644
--- a/src/vnet/devices/virtio/virtio.api
+++ b/src/vnet/devices/virtio/virtio.api
@@ -13,7 +13,7 @@
* limitations under the License.
*/
-option version = "2.0.0";
+option version = "3.0.0";
import "vnet/interface_types.api";
import "vnet/ethernet/ethernet_types.api";
@@ -32,6 +32,7 @@ import "vlib/pci/pci_types.api";
*/
define virtio_pci_create
{
+ option deprecated="21.01";
u32 client_index;
u32 context;
vl_api_pci_address_t pci_addr;
@@ -49,6 +50,47 @@ define virtio_pci_create
*/
define virtio_pci_create_reply
{
+ option deprecated="21.01";
+ u32 context;
+ i32 retval;
+ vl_api_interface_index_t sw_if_index;
+};
+
+enum virtio_flags {
+ VIRTIO_API_FLAG_GSO = 1, /* enable gso on the interface */
+ VIRTIO_API_FLAG_CSUM_OFFLOAD = 2, /* enable checksum offload without gso on the interface */
+ VIRTIO_API_FLAG_GRO_COALESCE = 4, /* enable packet coalescing on tx side, provided gso enabled */
+ VIRTIO_API_FLAG_PACKED = 8, /* enable packed ring support, provided it is available from backend */
+ VIRTIO_API_FLAG_IN_ORDER = 16, /* enable in order support, provided it is available from backend */
+};
+
+/** \brief Initialize a new virtio pci interface with the given parameters
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param pci_addr - pci address
+ @param use_random_mac - let the system generate a unique mac address
+ @param mac_address - mac addr to assign to the interface if use_random not set
+ @param virtio_flags - feature flags to enable
+ @param features - the virtio features which driver should negotiate with device
+*/
+define virtio_pci_create_v2
+{
+ u32 client_index;
+ u32 context;
+ vl_api_pci_address_t pci_addr;
+ bool use_random_mac;
+ vl_api_mac_address_t mac_address;
+ vl_api_virtio_flags_t virtio_flags;
+ u64 features;
+};
+
+/** \brief Reply for virtio pci create reply
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+ @param sw_if_index - software index allocated for the new virtio pci interface
+*/
+define virtio_pci_create_v2_reply
+{
u32 context;
i32 retval;
vl_api_interface_index_t sw_if_index;
diff --git a/src/vnet/devices/virtio/virtio_api.c b/src/vnet/devices/virtio/virtio_api.c
index 96ed927dc38..9a145d94a41 100644
--- a/src/vnet/devices/virtio/virtio_api.c
+++ b/src/vnet/devices/virtio/virtio_api.c
@@ -47,9 +47,11 @@
#define foreach_virtio_pci_api_msg \
_(VIRTIO_PCI_CREATE, virtio_pci_create) \
+_(VIRTIO_PCI_CREATE_V2, virtio_pci_create_v2) \
_(VIRTIO_PCI_DELETE, virtio_pci_delete) \
_(SW_INTERFACE_VIRTIO_PCI_DUMP, sw_interface_virtio_pci_dump)
+/* It will be deprecated in 21.01 */
static void
vl_api_virtio_pci_create_t_handler (vl_api_virtio_pci_create_t * mp)
{
@@ -94,6 +96,65 @@ vl_api_virtio_pci_create_t_handler (vl_api_virtio_pci_create_t * mp)
}
static void
+vl_api_virtio_pci_create_v2_t_handler (vl_api_virtio_pci_create_v2_t * mp)
+{
+ vlib_main_t *vm = vlib_get_main ();
+ vl_api_virtio_pci_create_v2_reply_t *rmp;
+ vl_api_registration_t *reg;
+ virtio_pci_create_if_args_t _a, *ap = &_a;
+
+ clib_memset (ap, 0, sizeof (*ap));
+
+ pci_address_decode (&mp->pci_addr, (vlib_pci_addr_t *) & ap->addr);
+ if (!mp->use_random_mac)
+ {
+ clib_memcpy (ap->mac_addr, mp->mac_address, 6);
+ ap->mac_addr_set = 1;
+ }
+ ap->sw_if_index = (u32) ~ 0;
+
+ STATIC_ASSERT (((int) VIRTIO_API_FLAG_GSO == (int) VIRTIO_FLAG_GSO),
+ "virtio gso api flag mismatch");
+ STATIC_ASSERT (((int) VIRTIO_API_FLAG_CSUM_OFFLOAD ==
+ (int) VIRTIO_FLAG_CSUM_OFFLOAD),
+ "virtio checksum offload api flag mismatch");
+ STATIC_ASSERT (((int) VIRTIO_API_FLAG_GRO_COALESCE ==
+ (int) VIRTIO_FLAG_GRO_COALESCE),
+ "virtio gro coalesce api flag mismatch");
+ STATIC_ASSERT (((int) VIRTIO_API_FLAG_PACKED == (int) VIRTIO_FLAG_PACKED),
+ "virtio packed api flag mismatch");
+ STATIC_ASSERT (((int) VIRTIO_API_FLAG_IN_ORDER ==
+ (int) VIRTIO_FLAG_IN_ORDER),
+ "virtio in-order api flag mismatch");
+
+ ap->virtio_flags = clib_net_to_host_u32 (mp->virtio_flags);
+ ap->features = clib_net_to_host_u64 (mp->features);
+
+ if (ap->virtio_flags & VIRTIO_FLAG_GSO)
+ ap->gso_enabled = 1;
+ else
+ ap->gso_enabled = 0;
+ if (ap->virtio_flags & VIRTIO_FLAG_CSUM_OFFLOAD)
+ ap->checksum_offload_enabled = 1;
+ else
+ ap->checksum_offload_enabled = 0;
+
+ virtio_pci_create_if (vm, ap);
+
+ reg = vl_api_client_index_to_registration (mp->client_index);
+ if (!reg)
+ return;;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = htons (VL_API_VIRTIO_PCI_CREATE_V2_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = htonl (ap->rv);
+ rmp->sw_if_index = htonl (ap->sw_if_index);
+
+ vl_api_send_msg (reg, (u8 *) rmp);
+}
+
+static void
vl_api_virtio_pci_delete_t_handler (vl_api_virtio_pci_delete_t * mp)
{
vnet_main_t *vnm = vnet_get_main ();
* from util import NumericConstant class BFDDiagCode(NumericConstant): """ BFD Diagnostic Code """ no_diagnostic = 0 control_detection_time_expired = 1 echo_function_failed = 2 neighbor_signaled_session_down = 3 forwarding_plane_reset = 4 path_down = 5 concatenated_path_down = 6 administratively_down = 7 reverse_concatenated_path_down = 8 desc_dict = { no_diagnostic: "No diagnostic", control_detection_time_expired: "Control Detection Time Expired", echo_function_failed: "Echo Function Failed", neighbor_signaled_session_down: "Neighbor Signaled Session Down", forwarding_plane_reset: "Forwarding Plane Reset", path_down: "Path Down", concatenated_path_down: "Concatenated Path Down", administratively_down: "Administratively Down", reverse_concatenated_path_down: "Reverse Concatenated Path Down", } def __init__(self, value): NumericConstant.__init__(self, value) class BFDState(NumericConstant): """ BFD State """ admin_down = 0 down = 1 init = 2 up = 3 desc_dict = { admin_down: "AdminDown", down: "Down", init: "Init", up: "Up", } def __init__(self, value): NumericConstant.__init__(self, value) class BFD(Packet): udp_dport = 3784 #: BFD destination port per RFC 5881 udp_sport_min = 49152 #: BFD source port min value per RFC 5881 udp_sport_max = 65535 #: BFD source port max value per RFC 5881 name = "BFD" fields_desc = [ BitField("version", 1, 3), BitEnumField("diag", 0, 5, BFDDiagCode.desc_dict), BitEnumField("state", 0, 2, BFDState.desc_dict), FlagsField("flags", 0, 6, ['P', 'F', 'C', 'A', 'D', 'M']), XByteField("detect_mult", 0), XByteField("length", 24), BitField("my_discriminator", 0, 32), BitField("your_discriminator", 0, 32), BitField("desired_min_tx_interval", 0, 32), BitField("required_min_rx_interval", 0, 32), BitField("required_min_echo_rx_interval", 0, 32)] def mysummary(self): return self.sprintf("BFD(my_disc=%BFD.my_discriminator%," "your_disc=%BFD.your_discriminator%)") # glue the BFD packet class to scapy parser bind_layers(UDP, BFD, dport=BFD.udp_dport) class VppBFDUDPSession(VppObject): """ Represents BFD UDP session in VPP """ @property def test(self): """ Test which created this session """ return self._test @property def interface(self): """ Interface on which this session lives """ return self._interface @property def af(self): """ Address family - AF_INET or AF_INET6 """ return self._af @property def bs_index(self): """ BFD session index from VPP """ if self._bs_index is not None: return self._bs_index raise NotConfiguredException("not configured") @property def local_addr(self): """ BFD session local address (VPP address) """ if self._local_addr is None: return self._interface.local_ip4 return self._local_addr @property def local_addr_n(self): """ BFD session local address (VPP address) - raw, suitable for API """ if self._local_addr is None: return self._interface.local_ip4n return self._local_addr_n @property def peer_addr(self): """ BFD session peer address """ return self._peer_addr @property def peer_addr_n(self): """ BFD session peer address - raw, suitable for API """ return self._peer_addr_n @property def state(self): """ BFD session state """ result = self.test.vapi.bfd_udp_session_dump() session = None for s in result: if s.sw_if_index == self.interface.sw_if_index: if self.af == AF_INET \ and s.is_ipv6 == 0 \ and self.interface.local_ip4n == s.local_addr[:4] \ and self.interface.remote_ip4n == s.peer_addr[:4]: session = s break if session is None: raise Exception( "Could not find BFD session in VPP response: %s" % repr(result)) return session.state @property def desired_min_tx(self): return self._desired_min_tx @property def required_min_rx(self): return self._required_min_rx @property def detect_mult(self): return self._detect_mult def __init__(self, test, interface, peer_addr, local_addr=None, af=AF_INET): self._test = test self._interface = interface self._af = af self._local_addr = local_addr self._peer_addr = peer_addr self._peer_addr_n = socket.inet_pton(af, peer_addr) self._bs_index = None self._desired_min_tx = 200000 # 0.2s self._required_min_rx = 200000 # 0.2s self._detect_mult = 3 # 3 packets need to be missed def add_vpp_config(self): is_ipv6 = 1 if AF_INET6 == self.af else 0 result = self.test.vapi.bfd_udp_add( self._interface.sw_if_index, self.desired_min_tx, self.required_min_rx, self.detect_mult, self.local_addr_n, self.peer_addr_n, is_ipv6=is_ipv6) self._bs_index = result.bs_index def query_vpp_config(self): result = self.test.vapi.bfd_udp_session_dump() session = None for s in result: if s.sw_if_index == self.interface.sw_if_index: if self.af == AF_INET \ and s.is_ipv6 == 0 \ and self.interface.local_ip4n == s.local_addr[:4] \ and self.interface.remote_ip4n == s.peer_addr[:4]: session = s break if session is None: return False return True def remove_vpp_config(self): if hasattr(self, '_bs_index'): is_ipv6 = 1 if AF_INET6 == self._af else 0 self.test.vapi.bfd_udp_del( self._interface.sw_if_index, self.local_addr_n, self.peer_addr_n, is_ipv6=is_ipv6) def object_id(self): return "bfd-udp-%d" % self.bs_index def admin_up(self): self.test.vapi.bfd_session_set_flags(self.bs_index, 1)