-
Notifications
You must be signed in to change notification settings - Fork 740
Sockets dimensioned by Num queues #2000
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
9d030cd
09f8145
7fc2796
79b06f5
b565c74
943f7bd
739fd67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,10 @@ | |
| /// @ | ||
| namespace pcpp | ||
| { | ||
|
|
||
| // used to dimension sockets | ||
| #define MAXIMUM_NUMBER_QUEUES 8 | ||
|
|
||
| /// @class XdpDevice | ||
| /// A class wrapping the main functionality of using AF_XDP (XSK) sockets | ||
| /// which are optimized for high performance packet processing. | ||
|
|
@@ -47,6 +51,10 @@ namespace pcpp | |
| /// AF_XDP operation mode | ||
| AttachMode attachMode; | ||
|
|
||
| /// number of queues. Should be less than or equal to the number of hardware queues supported by the device | ||
| // the queue ids are inferred as consecutive starting at zero | ||
| uint32_t numQueues; | ||
|
|
||
| /// UMEM is a region of virtual contiguous memory, divided into equal-sized frames. | ||
| /// This parameter determines the number of frames that will be allocated as pert of the UMEM. | ||
| uint16_t umemNumFrames; | ||
|
|
@@ -89,7 +97,7 @@ namespace pcpp | |
| explicit XdpDeviceConfiguration(AttachMode attachMode = AutoMode, uint16_t umemNumFrames = 0, | ||
| uint16_t umemFrameSize = 0, uint32_t fillRingSize = 0, | ||
| uint32_t completionRingSize = 0, uint32_t rxSize = 0, uint32_t txSize = 0, | ||
| uint16_t rxTxBatchSize = 0) | ||
| uint16_t rxTxBatchSize = 0, uint32_t numQueues = 0) | ||
| { | ||
| this->attachMode = attachMode; | ||
| this->umemNumFrames = umemNumFrames; | ||
|
|
@@ -99,6 +107,7 @@ namespace pcpp | |
| this->rxSize = rxSize; | ||
| this->txSize = txSize; | ||
| this->rxTxBatchSize = rxTxBatchSize; | ||
| this->numQueues = numQueues; | ||
| } | ||
| }; | ||
|
|
||
|
|
@@ -196,11 +205,11 @@ namespace pcpp | |
| /// ms | ||
| /// @return True if stopped receiving packets because stopReceivePackets() was called or because timeoutMS | ||
| /// passed, or false if an error occurred. | ||
| bool receivePackets(OnPacketsArrive onPacketsArrive, void* onPacketsArriveUserCookie, int timeoutMS = 5000); | ||
| bool receivePackets(OnPacketsArrive onPacketsArrive, void* onPacketsArriveUserCookie, int timeoutMS = 5000, uint32_t queueid = 0); | ||
|
|
||
| /// Stop receiving packets. Call this method from within the callback passed to receivePackets() whenever you | ||
| /// want to stop receiving packets. | ||
| void stopReceivePackets(); | ||
| void stopReceivePackets(uint32_t queueid = 0); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would the user call the correct queue id from inside the receive loop ( Of course, they can save it externally or in the user cookie, but that seems like a code smell to me, as it should be provided to them in the callback. @seladb IMO, it would be useful if the callback signature be changed to have a param Alternative is to have the callback require a
|
||
|
|
||
| /// Send a vector of packet pointers. | ||
| /// @param[in] packets A vector of packet pointers to send | ||
|
|
@@ -212,7 +221,7 @@ namespace pcpp | |
| /// @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. | ||
| /// Returns false if an error occurred or if poll timed out. | ||
| bool sendPackets(const RawPacketVector& packets, bool waitForTxCompletion = false, | ||
| int waitForTxCompletionTimeoutMS = 5000); | ||
| int waitForTxCompletionTimeoutMS = 5000, uint32_t queueid = 0); | ||
|
|
||
| /// Send an array of packets. | ||
| /// @param[in] packets An array of raw packets to send | ||
|
|
@@ -225,7 +234,7 @@ namespace pcpp | |
| /// @return True if all packets were sent, or if waitForTxCompletion is true - all sent packets were confirmed. | ||
| /// Returns false if an error occurred or if poll timed out. | ||
| bool sendPackets(RawPacket packets[], size_t packetCount, bool waitForTxCompletion = false, | ||
| int waitForTxCompletionTimeoutMS = 5000); | ||
| int waitForTxCompletionTimeoutMS = 5000, uint32_t queueid = 0); | ||
|
|
||
| /// @return A pointer to the current device configuration. If the device is not open this method returns nullptr | ||
| XdpDeviceConfiguration* getConfig() const | ||
|
|
@@ -234,7 +243,7 @@ namespace pcpp | |
| } | ||
|
|
||
| /// @return Current device statistics | ||
| XdpDeviceStats getStatistics(); | ||
| XdpDeviceStats getStatistics(uint32_t queueid = 0); | ||
|
|
||
| private: | ||
| class XdpUmem | ||
|
|
@@ -294,21 +303,22 @@ namespace pcpp | |
|
|
||
| std::string m_InterfaceName; | ||
| XdpDeviceConfiguration* m_Config; | ||
| bool m_ReceivingPackets; | ||
| XdpUmem* m_Umem; | ||
| void* m_SocketInfo; | ||
| XdpDeviceStats m_Stats; | ||
| XdpPrevDeviceStats m_PrevStats; | ||
| uint32_t m_NumQueues; | ||
| bool m_ReceivingPackets[MAXIMUM_NUMBER_QUEUES]; | ||
| XdpUmem* m_Umem[MAXIMUM_NUMBER_QUEUES]; | ||
| void* m_SocketInfo[MAXIMUM_NUMBER_QUEUES]; | ||
| XdpDeviceStats m_Stats[MAXIMUM_NUMBER_QUEUES]; | ||
| XdpPrevDeviceStats m_PrevStats[MAXIMUM_NUMBER_QUEUES]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We prefer IMO, the main benefit is the addition of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. I was just seeing how things propagate with the added dimension. I will make this change on my fork.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Additionally, I am debating on the viability of encapsulating a single open socket in The current API can either forward to the selected socket (via queueId), or remain unchanged and be made to operate on all open sockets (except receive and send, those default to queue 0 for backwards compat). If option 2 is taken, The idea is because most elements are accessed on a "per thread queue" basis instead of "per array type" and would somewhat clean up the Any thoughts?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think so. Would the Xdp hold the socket info, queueid, and the umem parts? I am still groping around with XDP but it seems to be a natural progression.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Essentially, yes. The
It can be a POD struct that just holds them for the device to use, or it can be a full class with its own methods (essentially some of the current I somewhat like the full object solution, as it would provide simpler methods in the API.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would make it a class subordinate to the XdpDevice namespace. I can start there and see how it pans out. For now might we define the Umem region part of the XdpSocket too since it's dimensioned that way currently,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I pushed something that encapsulates in a Socket class. |
||
|
|
||
| bool sendPackets(const std::function<RawPacket(uint32_t)>& getPacketAt, | ||
| const std::function<uint32_t()>& getPacketCount, bool waitForTxCompletion = false, | ||
| int waitForTxCompletionTimeoutMS = 5000); | ||
| bool populateFillRing(uint32_t count, uint32_t rxId = 0); | ||
| bool populateFillRing(const std::vector<uint64_t>& addresses, uint32_t rxId); | ||
| uint32_t checkCompletionRing(); | ||
| bool configureSocket(); | ||
| bool initUmem(); | ||
| int waitForTxCompletionTimeoutMS = 5000, uint32_t queueid = 0); | ||
| bool populateFillRing(uint32_t count, uint32_t rxId = 0, uint32_t queueid = 0); | ||
| bool populateFillRing(const std::vector<uint64_t>& addresses, uint32_t rxId, uint32_t queueid = 0); | ||
| uint32_t checkCompletionRing(uint32_t queueid = 0); | ||
| bool configureSocket(uint32_t queueid = 0); | ||
| bool initUmem(uint32_t queueid = 0); | ||
| bool initConfig(); | ||
| bool getSocketStats(); | ||
| bool getSocketStats(uint32_t queueid = 0); | ||
| }; | ||
| } // namespace pcpp | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For hard constants, prefer using C++
const/constexprvariables.If macros are needed in public headers, prefix them with
PCPP_so they don't conflict with other macros the users might have.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok---perhaps with the std::array I don't need this definition any more