X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fnetdev.c;h=150f8d851be362ee532bc383122c97c49bdbed25;hb=e175dc83c5772438466bafb23a17ceb2e052e1c2;hp=9d391634b0985cb4dcf7ebd4e62ec5f3fd5b553b;hpb=d625fbd13ec3254981df5000bf2587d715401f36;p=cascardo%2Fovs.git diff --git a/lib/netdev.c b/lib/netdev.c index 9d391634b..150f8d851 100644 --- a/lib/netdev.c +++ b/lib/netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -106,12 +106,19 @@ netdev_n_rxq(const struct netdev *netdev) return netdev->n_rxq; } +int +netdev_requested_n_rxq(const struct netdev *netdev) +{ + return netdev->requested_n_rxq; +} + bool netdev_is_pmd(const struct netdev *netdev) { return (!strcmp(netdev->netdev_class->type, "dpdk") || !strcmp(netdev->netdev_class->type, "dpdkr") || - !strcmp(netdev->netdev_class->type, "dpdkvhost")); + !strcmp(netdev->netdev_class->type, "dpdkvhostcuse") || + !strcmp(netdev->netdev_class->type, "dpdkvhostuser")); } static void @@ -257,6 +264,8 @@ netdev_unregister_provider(const char *type) struct netdev_registered_class *rc; int error; + netdev_initialize(); + ovs_mutex_lock(&netdev_class_mutex); rc = netdev_lookup_class(type); if (!rc) { @@ -373,6 +382,7 @@ netdev_open(const char *name, const char *type, struct netdev **netdevp) /* By default enable one tx and rx queue per netdev. */ netdev->n_txq = netdev->netdev_class->send ? 1 : 0; netdev->n_rxq = netdev->netdev_class->rxq_alloc ? 1 : 0; + netdev->requested_n_rxq = netdev->n_rxq; list_init(&netdev->saved_flags_list); @@ -629,28 +639,28 @@ netdev_rxq_close(struct netdev_rxq *rx) } } -/* Attempts to receive batch of packets from 'rx'. +/* Attempts to receive a batch of packets from 'rx'. 'pkts' should point to + * the beginning of an array of MAX_RX_BATCH pointers to dp_packet. If + * successful, this function stores pointers to up to MAX_RX_BATCH dp_packets + * into the array, transferring ownership of the packets to the caller, stores + * the number of received packets into '*cnt', and returns 0. * - * Returns EAGAIN immediately if no packet is ready to be received. + * The implementation does not necessarily initialize any non-data members of + * 'pkts'. That is, the caller must initialize layer pointers and metadata + * itself, if desired, e.g. with pkt_metadata_init() and miniflow_extract(). * - * Returns EMSGSIZE, and discards the packet, if the received packet is longer - * than 'dp_packet_tailroom(buffer)'. - * - * It is advised that the tailroom of 'buffer' should be - * VLAN_HEADER_LEN bytes longer than the MTU to allow space for an - * out-of-band VLAN header to be added to the packet. At the very least, - * 'buffer' must have at least ETH_TOTAL_MIN bytes of tailroom. - * - * This function may be set to null if it would always return EOPNOTSUPP - * anyhow. */ + * Returns EAGAIN immediately if no packet is ready to be received or another + * positive errno value if an error was encountered. */ int -netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet **buffers, int *cnt) +netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet **pkts, int *cnt) { int retval; - retval = rx->netdev->netdev_class->rxq_recv(rx, buffers, cnt); + retval = rx->netdev->netdev_class->rxq_recv(rx, pkts, cnt); if (!retval) { COVERAGE_INC(netdev_received); + } else { + *cnt = 0; } return retval; } @@ -675,6 +685,16 @@ netdev_rxq_drain(struct netdev_rxq *rx) /* Configures the number of tx queues and rx queues of 'netdev'. * Return 0 if successful, otherwise a positive errno value. * + * 'n_rxq' specifies the maximum number of receive queues to create. + * The netdev provider might choose to create less (e.g. if the hardware + * supports only a smaller number). The caller can check how many have been + * actually created by calling 'netdev_n_rxq()' + * + * 'n_txq' specifies the exact number of transmission queues to create. + * If this function returns successfully, the caller can make 'n_txq' + * concurrent calls to netdev_send() (each one with a different 'qid' in the + * range [0..'n_txq'-1]). + * * On error, the tx queue and rx queue configuration is indeterminant. * Caller should make decision on whether to restore the previous or * the default configuration. Also, caller must make sure there is no @@ -708,7 +728,9 @@ netdev_set_multiq(struct netdev *netdev, unsigned int n_txq, * If the function returns a non-zero value, some of the packets might have * been sent anyway. * - * To retain ownership of 'buffer' caller can set may_steal to false. + * If 'may_steal' is false, the caller retains ownership of all the packets. + * If 'may_steal' is true, the caller transfers ownership of all the packets + * to the network device, regardless of success. * * The network device is expected to maintain one or more packet * transmission queues, so that the caller does not ordinarily have to @@ -722,11 +744,17 @@ int netdev_send(struct netdev *netdev, int qid, struct dp_packet **buffers, int cnt, bool may_steal) { - int error; + if (!netdev->netdev_class->send) { + if (may_steal) { + for (int i = 0; i < cnt; i++) { + dp_packet_delete(buffers[i]); + } + } + return EOPNOTSUPP; + } - error = (netdev->netdev_class->send - ? netdev->netdev_class->send(netdev, qid, buffers, cnt, may_steal) - : EOPNOTSUPP); + int error = netdev->netdev_class->send(netdev, qid, buffers, cnt, + may_steal); if (!error) { COVERAGE_INC(netdev_sent); } @@ -747,8 +775,7 @@ netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers, int cnt) err = netdev->netdev_class->pop_header(buffers[i]); if (err) { - struct flow_tnl *tunnel_md = &buffers[i]->md.tunnel; - memset(tunnel_md, 0, sizeof *tunnel_md); + dp_packet_clear(buffers[i]); } } @@ -778,7 +805,7 @@ netdev_push_header(const struct netdev *netdev, for (i = 0; i < cnt; i++) { netdev->netdev_class->push_header(buffers[i], data); - buffers[i]->md = PKT_METADATA_INITIALIZER(u32_to_odp(data->out_port)); + pkt_metadata_init(&buffers[i]->md, u32_to_odp(data->out_port)); } return 0; @@ -804,7 +831,7 @@ netdev_send_wait(struct netdev *netdev, int qid) /* Attempts to set 'netdev''s MAC address to 'mac'. Returns 0 if successful, * otherwise a positive errno value. */ int -netdev_set_etheraddr(struct netdev *netdev, const uint8_t mac[ETH_ADDR_LEN]) +netdev_set_etheraddr(struct netdev *netdev, const struct eth_addr mac) { return netdev->netdev_class->set_etheraddr(netdev, mac); } @@ -813,7 +840,7 @@ netdev_set_etheraddr(struct netdev *netdev, const uint8_t mac[ETH_ADDR_LEN]) * the MAC address into 'mac'. On failure, returns a positive errno value and * clears 'mac' to all-zeros. */ int -netdev_get_etheraddr(const struct netdev *netdev, uint8_t mac[ETH_ADDR_LEN]) +netdev_get_etheraddr(const struct netdev *netdev, struct eth_addr *mac) { return netdev->netdev_class->get_etheraddr(netdev, mac); } @@ -1247,13 +1274,13 @@ netdev_restore_flags(struct netdev_saved_flags *sf) * ENXIO indicates that there is no ARP table entry for 'ip' on 'netdev'. */ int netdev_arp_lookup(const struct netdev *netdev, - ovs_be32 ip, uint8_t mac[ETH_ADDR_LEN]) + ovs_be32 ip, struct eth_addr *mac) { int error = (netdev->netdev_class->arp_lookup ? netdev->netdev_class->arp_lookup(netdev, ip, mac) : EOPNOTSUPP); if (error) { - memset(mac, 0, ETH_ADDR_LEN); + *mac = eth_addr_zero; } return error; } @@ -1788,6 +1815,12 @@ netdev_rxq_get_name(const struct netdev_rxq *rx) return netdev_get_name(netdev_rxq_get_netdev(rx)); } +int +netdev_rxq_get_queue_id(const struct netdev_rxq *rx) +{ + return rx->queue_id; +} + static void restore_all_flags(void *aux OVS_UNUSED) {