1 /*
2  * Copyright (c) 2014, Cisco Systems, Inc. All rights reserved.
3  *
4  * LICENSE_BEGIN
5  *
6  * This software is available to you under a choice of one of two
7  * licenses.  You may choose to be licensed under the terms of the GNU
8  * General Public License (GPL) Version 2, available from the file
9  * COPYING in the main directory of this source tree, or the
10  * BSD license below:
11  *
12  *     Redistribution and use in source and binary forms, with or
13  *     without modification, are permitted provided that the following
14  *     conditions are met:
15  *
16  *      - Redistributions of source code must retain the above
17  *        copyright notice, this list of conditions and the following
18  *        disclaimer.
19  *
20  *      - Redistributions in binary form must reproduce the above
21  *        copyright notice, this list of conditions and the following
22  *        disclaimer in the documentation and/or other materials
23  *        provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * LICENSE_END
39  *
40  *
41  */
42 
43 #ifndef _USNIC_DIRECT_H_
44 #define _USNIC_DIRECT_H_
45 
46 #include <sys/types.h>
47 #include <net/if.h>
48 #include <netinet/in.h>
49 #include <net/ethernet.h>
50 #include <netinet/ip.h>
51 #include <netinet/udp.h>
52 
53 #define USD_MAX_DEVICES 8
54 #define USD_MAX_DEVNAME 16
55 #define USD_RECV_MAX_SGE 8
56 #define USD_SEND_MAX_SGE 8
57 
58 enum usd_link_state {
59     USD_LINK_DOWN,
60     USD_LINK_UP
61 };
62 
63 /* forward structure defs */
64 struct usd_context;
65 struct usd_qp;
66 struct usd_device;
67 struct usd_dest;
68 struct usd_connection;
69 struct usd_mr;
70 
71 struct usd_device_attrs {
72     char uda_devname[USD_MAX_DEVNAME];
73     char uda_ifname[IFNAMSIZ];
74     int uda_ifindex;
75     uint8_t uda_mac_addr[ETH_ALEN];
76 
77     /* IP config */
78     uint32_t uda_ipaddr_be;
79     uint32_t uda_netmask_be;
80     uint32_t uda_prefixlen;        /* netmask length */
81     uint32_t uda_mtu;
82     enum usd_link_state uda_link_state;
83 
84     /* HW info */
85     uint32_t uda_vendor_id;
86     uint32_t uda_vendor_part_id;
87     uint32_t uda_device_id;
88     char uda_firmware[64];
89 
90     /* usnic config */
91     unsigned uda_num_vf;
92     unsigned uda_cq_per_vf;
93     unsigned uda_qp_per_vf;
94     unsigned uda_intr_per_vf;
95     unsigned uda_num_comp_vectors;
96     unsigned uda_max_cq;
97     unsigned uda_max_qp;
98 
99     /* VIC constants */
100     uint32_t uda_bandwidth;
101     unsigned uda_max_cqe;
102     unsigned uda_max_send_credits;
103     unsigned uda_max_recv_credits;
104 
105     /* fd that can be used to poll for device events */
106     int uda_event_fd;
107 };
108 
109 enum usd_completion_status {
110     USD_COMPSTAT_SUCCESS,
111     USD_COMPSTAT_ERROR_CRC,
112     USD_COMPSTAT_ERROR_TRUNC,
113     USD_COMPSTAT_ERROR_TIMEOUT,
114     USD_COMPSTAT_ERROR_INTERNAL
115 };
116 enum usd_completion_type {
117     USD_COMPTYPE_SEND=0,
118     USD_COMPTYPE_RECV=7,
119 };
120 
121 struct usd_completion {
122     enum usd_completion_status uc_status;
123     enum usd_completion_type uc_type;
124     uint32_t uc_bytes;
125     uint16_t uc_rkey;
126     struct usd_qp *uc_qp;
127     void *uc_context;
128     u_int16_t uc_retrans;
129 };
130 
131 struct usd_recv_desc {
132     void *urd_context;
133     struct iovec urd_iov[USD_RECV_MAX_SGE];
134     size_t urd_iov_cnt;
135     struct usd_recv_desc *urd_next;
136 };
137 
138 /*
139  * Operations that may vary based on transport/QP type
140  */
141 struct usd_qp_ops {
142     int (*qo_post_send_one)(struct usd_qp *qp,
143             struct usd_dest *dest, const void *buf, size_t len,
144             uint32_t flags, void *context);
145     int (*qo_post_send_one_prefixed)(struct usd_qp *qp,
146             struct usd_dest *dest, const void *buf, size_t len,
147             uint32_t flags, void *context);
148     int (*qo_post_send_one_copy)(struct usd_qp *qp,
149             struct usd_dest *dest, const void *buf, size_t len,
150             uint32_t flags, void *context);
151     int (*qo_post_send_two_copy)(struct usd_qp *qp,
152             struct usd_dest *dest, const void *hdr, size_t hdrlen,
153             const void *pkt, size_t pktlen, uint32_t flags, void *context);
154     int (*qo_post_send_iov)(struct usd_qp *qp,
155             struct usd_dest *dest, const struct iovec* iov,
156             size_t iov_count, uint32_t flags, void *context);
157     int (*qo_post_send_one_vlan)(struct usd_qp *qp,
158             struct usd_dest *dest, const void *buf, size_t len,
159             u_int16_t vlan, uint32_t flags, void *context);
160 };
161 
162 /*
163  * user's view of a CQ
164  */
165 struct usd_cq {
166     unsigned ucq_num_entries;
167 };
168 
169 /*
170  * User's view of a QP
171  */
172 struct usd_qp {
173     struct usd_qp_ops uq_ops;
174     void *uq_context;           /* place for user to scribble */
175 };
176 
177 /*
178  * Filters for QPs
179  */
180 enum usd_filter_type {
181     USD_FTY_UDP,
182     USD_FTY_UDP_SOCK,
183     USD_FTY_TCP,
184     USD_FTY_MCAST,
185     USD_FTY_8915
186 };
187 struct usd_filter {
188     enum usd_filter_type uf_type;
189     union {
190         struct {
191             uint16_t u_port;
192         } uf_udp;
193         struct {
194             int u_sock;
195         } uf_udp_sock;
196         struct {
197             int t_sock;
198             struct sockaddr_in t_remote;
199         } uf_tcp;
200         struct {
201             struct sockaddr_in m_addr;
202         } uf_mcast;
203     } uf_filter;
204 };
205 
206 /*
207  * Local address - much like a filter
208  * Type is defined by transport specified in create_qp
209  */
210 struct usd_local_addr {
211     union {
212         struct {
213             struct sockaddr_in u_addr;
214         } ul_udp;
215         struct {
216             uint32_t qp_num;
217         } ul_8915;
218     } ul_addr;
219 };
220 
221 enum usd_qp_transport {
222     USD_QTR_RAW,    /* no header added */
223     USD_QTR_UDP    /* create UDP header based on dest */
224 };
225 
226 enum usd_qp_type {
227     USD_QTY_UD,
228     USD_QTY_UD_PIO,
229 };
230 
231 /*
232  * Attributes of a queue pair
233  */
234 struct usd_qp_attrs {
235     enum usd_qp_transport uqa_transport;
236     enum usd_qp_type uqa_qtype;
237     struct usd_local_addr uqa_local_addr;
238 
239     unsigned uqa_max_send_credits;
240     unsigned uqa_max_recv_credits;
241     uint64_t uqa_pio_paddr;
242 
243     unsigned uqa_max_inline;
244     unsigned uqa_hdr_len;    /* length of header for this QP */
245 };
246 
247 /*
248  * Description of a device event which has occurred
249  */
250 enum usd_device_event_type {
251     USD_EVENT_LINK_UP,
252     USD_EVENT_LINK_DOWN
253 };
254 struct usd_device_event {
255     union {
256         void *ude_context;
257     } ude_context;
258     enum usd_device_event_type ude_type;
259 };
260 
261 /*
262  * Returned form usd_get_available_devices() - array of currently
263  * available usd device names
264  */
265 struct usd_device_entry {
266     char ude_devname[USD_MAX_DEVNAME];
267 };
268 
269 /*
270  * Send flags
271  */
272 enum usd_send_flag_shift {
273     USD_SFS_SIGNAL,
274 };
275 #define USD_SF_SIGNAL (1 << USD_SFS_SIGNAL)
276 
277  /*
278  * cq creation parameters
279  */
280 struct usd_cq_init_attr {
281     unsigned num_entries;           /* number of requested cq elements */
282     int comp_fd;                    /* completion fd */
283     int comp_vec;                   /* requested completion vector */
284     int comp_req_notify;            /* whether need to request notify for each completion */
285     void *ibv_cq;                   /* verbs userspace cq object if signaling through uverbs */
286 };
287 
288 /*
289  * Headers for defined transport types
290  */
291 struct usd_udp_hdr {
292     struct ether_header uh_eth;
293     struct iphdr uh_ip;
294     struct udphdr uh_udp;
295 } __attribute__ ((__packed__));
296 
297 /*
298  * Struct and defines for usd open parameters
299  */
300 #define UOPF_SKIP_LINK_CHECK 0x1
301 #define UOPF_SKIP_PD_ALLOC  0x2
302 
303 struct usd_open_params {
304     int flags;
305     int cmd_fd;
306     struct usd_context *context;
307 };
308 
309 /*
310  ****************************************************************
311  * Device management
312  ****************************************************************
313  */
314 int usd_get_device_list(struct usd_device_entry *dev_array,
315         int *num_devs);
316 
317 int usd_open(const char *devname, struct usd_device **dev_o);
318 
319 int usd_open_with_params(const char *dev_name,
320                             struct usd_open_params *uop_param,
321                             struct usd_device **dev_o);
322 
323 int usd_close(struct usd_device *dev);
324 
325 int usd_get_device_attrs(struct usd_device *dev,
326         struct usd_device_attrs *attr);
327 
328 int usd_get_device_event(struct usd_device *dev,
329         struct usd_device_event *event);
330 
331 enum usd_capability {
332     USD_CAP_CQ_SHARING,
333     USD_CAP_MAP_PER_RES,
334     USD_CAP_PIO,
335     USD_CAP_CQ_INTR,
336     USD_CAP_GRP_INTR,
337     USD_CAP_MAX
338 };
339 int usd_get_cap(struct usd_device *dev, enum usd_capability cap);
340 
341 /*
342  ****************************************************************
343  * Queue management
344  ****************************************************************
345  */
346 
347 /*
348  * Get a file descriptor which can be used to poll for completions.  The
349  * returned file descriptor will be different on each call to
350  * usd_get_completion_fd, so that coordination is not needed when using these
351  * fds in syscalls like poll(2).
352  */
353 int usd_get_completion_fd(struct usd_device *dev, int *comp_fd_o);
354 
355 int usd_put_completion_fd(struct usd_device *dev, int comp_fd);
356 
357 /*
358  * Request a CQ with specified attributes:
359  *   dev - device on which to create this CQ
360  *   init_attr - CQ creation parameters
361  */
362 int usd_create_cq(struct usd_device *dev, struct usd_cq_init_attr *init_attr,
363                     struct usd_cq **cq_o);
364 
365 int usd_destroy_cq(struct usd_cq *cq);
366 
367 int usd_cq_intr_enable(struct usd_cq *cq);
368 int usd_cq_intr_disable(struct usd_cq *cq);
369 
370 /*
371  * Get and set interrupt coalescing delay, units are in microseconds
372  */
373 int usd_cq_set_intr_coal(struct usd_cq *cq, unsigned intr_coal_delay);
374 unsigned usd_cq_get_intr_coal(struct usd_cq *cq);
375 
376 /*
377  * IN:
378  *     dev - device on which QP is to be created
379  *     transport - what transport to use on this queue
380  *     type - type of queue to create
381  *     wcq - CQ handle for send completions
382  *     rcq - CQ handle for receive completions
383  *     send_credits - Number of send credits requested
384  *     recv_credite - Number of receive buffer credits requested
385  *     port - Requested local port for QP (0 lets library choose)
386  *     qp_o - Address to receive QP handle on successful completion
387  * OUT:
388  *     Returns 0 or code from errno.h
389  *      0 - successful completion
390  *      EBUSY - port is in use
391  *      XXX
392  */
393 int usd_create_qp(struct usd_device *dev,
394         enum usd_qp_transport transport,
395         enum usd_qp_type qtype,
396         struct usd_cq *wcq, struct usd_cq *rcq,
397         unsigned send_credits, unsigned recv_credits,
398         struct usd_filter *filt, struct usd_qp **qp_o);
399 
400 int usd_destroy_qp(struct usd_qp *qp);
401 
402 int usd_enable_qp(struct usd_qp *qp);
403 int usd_disable_qp(struct usd_qp *qp);
404 
405 int usd_get_qp_attrs(struct usd_qp *qp,
406         struct usd_qp_attrs *qp_attrs_o);
407 
408 /*
409  * Add a filter to a QP
410  */
411 int usd_qp_add_filter(struct usd_qp *qp, struct usd_filter *filter);
412 
413 /*
414  * Get current send credits
415  */
416 unsigned usd_get_send_credits(struct usd_qp *uqp);
417 
418 /*
419  * Get current recv credits
420  */
421 unsigned usd_get_recv_credits(struct usd_qp *uqp);
422 
423 /*
424  ****************************************************************
425  * Memory management
426  ****************************************************************
427  */
428 
429 int usd_reg_mr(struct usd_device *dev,
430         void *buffer, size_t size, struct usd_mr **mr_o);
431 int usd_dereg_mr(struct usd_mr *mr);
432 
433 int usd_alloc_mr(struct usd_device *dev, size_t size, void **vaddr_o);
434 int usd_free_mr(void *vaddr);
435 
436 /*
437  ****************************************************************
438  * Destination management
439  ****************************************************************
440  */
441 
442 /*
443  * Return the distance metric to a specified IP address
444  * Metric is:
445  *    0 - same VLAN
446  *    1..MAXINT - relative distance metric
447  *    -1 - unreachable
448  */
449 int usd_get_dest_distance(struct usd_device *dev, uint32_t daddr_be,
450         int *metric_o);
451 
452 /*
453  * Settings for address resolution timeout and retry
454  */
455 struct usd_dest_params {
456     unsigned dp_arp_timeout;    /* per-try timeout in ms */
457     unsigned dp_max_arps;
458 };
459 
460 /*
461  * Get address resolution settings
462  */
463 int usd_get_dest_params(struct usd_dest_params *params);
464 
465 /*
466  * Set address resolution settings
467  * Settings may not be changed while any resolution requests are in progress.
468  */
469 int usd_set_dest_params(struct usd_dest_params *params);
470 
471 /*
472  * Used to create a destination with MAC address is already known.
473  */
474 int usd_create_dest_with_mac(struct usd_device *dev, uint32_t daddr_be,
475                uint16_t port_be, uint8_t *dmac, struct usd_dest **dest_o);
476 
477 /*
478  * Synchronously creates a destination
479  */
480 int usd_create_dest(struct usd_device *dev, uint32_t daddr_be,
481                uint16_t port_be, struct usd_dest **dest_o);
482 
483 /*
484  * Start the necessary ARP resolution to create a destination
485  * Resolution progress is performed in usd_create_dest_query() and
486  * usd_create_dest_poll()
487  */
488 int usd_create_dest_start(struct usd_device *dev, uint32_t daddr_be,
489                uint16_t dport_be, void *context);
490 
491 /*
492  * Cancel resolution on a not-yet-completed create_dest request
493  */
494 int usd_create_dest_cancel(struct usd_device *dev, void *context);
495 
496 /*
497  * Extract dest port and IP from a destination
498  */
499 int usd_expand_dest(struct usd_dest *dest, uint32_t *dest_ip_be_o,
500         uint16_t *dest_port_be_o);
501 
502 /*
503  * Query completion status of a given create_dest request
504  * If complete, newly allocated destination is returned in dest_o
505  * Returns:
506  *    0 - request completed, *status is valid
507  *         dest_o valid if *status == 0
508  *    -EAGAIN - nothing is complete
509  *    other - negative errno code
510  */
511 int usd_create_dest_query(struct usd_device *dev, void *context, int *status,
512         struct usd_dest **dest_o);
513 
514 /*
515  * Checks for completed destination creation.
516  * context specified in call to usd_create_dest_start is returned,
517  * newly allocated destination is returned in dest_o
518  * Returns:
519  *    0 - request completed, status and context_o valid
520  *         dest_o valid if *status == 0
521  *    -EAGAIN - nothing is complete
522  *    other - negative errno code
523  */
524 int usd_create_dest_poll(struct usd_device *dev, void **context_o, int *status,
525         struct usd_dest **dest_o);
526 
527 
528 int usd_destroy_dest(struct usd_dest *dest);
529 
530 /*
531  ****************************************************************
532  * Sending, receiving, and completions
533  ****************************************************************
534  */
535 
536 /*
537  * Post a receive.  The number of receive credits consumed is equal
538  * to the number of entries in the SG list of the recv_desc, or
539  * recv_desc.urd_iov_cnt
540  */
541 int usd_post_recv(struct usd_qp *qp,
542         struct usd_recv_desc *recv_list);
543 
544 int usd_poll_cq_multi(struct usd_cq *cq, int max_comps,
545         struct usd_completion *comps);
546 int usd_poll_cq(struct usd_cq *cq, struct usd_completion *comp);
547 int usd_poll_req_notify(struct usd_cq *ucq);
548 
549 unsigned usd_get_send_credits(struct usd_qp *qp);
550 
551 unsigned usd_get_recv_credits(struct usd_qp *qp);
552 
553 /*
554  * post a single-buffer send from registered memory
555  * IN:
556  *     qp
557  *     dest
558  *     buf -
559  * Requires 2 send credits
560  */
561 static inline int
usd_post_send_one(struct usd_qp * qp,struct usd_dest * dest,const void * buf,size_t len,uint32_t flags,void * context)562 usd_post_send_one(
563     struct usd_qp *qp,
564     struct usd_dest *dest,
565     const void *buf,
566     size_t len,
567     uint32_t flags,
568     void *context)
569 {
570     return qp->uq_ops.qo_post_send_one(
571             qp, dest, buf, len, flags, context);
572 }
573 
574 /*
575  * post a single-buffer send from registered memory to specified VLAN
576  * IN:
577  *     qp
578  *     dest
579  *     buf -
580  * Requires 2 send credits
581  */
582 static inline int
usd_post_send_one_vlan(struct usd_qp * qp,struct usd_dest * dest,const void * buf,size_t len,u_int16_t vlan,uint32_t flags,void * context)583 usd_post_send_one_vlan(
584     struct usd_qp *qp,
585     struct usd_dest *dest,
586     const void *buf,
587     size_t len,
588     u_int16_t vlan,
589     uint32_t flags,
590     void *context)
591 {
592     return qp->uq_ops.qo_post_send_one_vlan(
593             qp, dest, buf, len, vlan, flags, context);
594 }
595 
596 /*
597  * post a single-buffer send from registered memory
598  * Caller must allow sufficient space *before* the packet for usd header
599  * For optimal efficieny, the buffer should be aligned on XXX boundary
600  * IN:
601  *     qp
602  *     dest
603  *     buf -
604  * Requires 1 send credit
605  */
606 static inline int
usd_post_send_one_prefixed(struct usd_qp * qp,struct usd_dest * dest,const void * buf,size_t len,uint32_t flags,void * context)607 usd_post_send_one_prefixed(
608     struct usd_qp *qp,
609     struct usd_dest *dest,
610     const void *buf,
611     size_t len,
612     uint32_t flags,
613     void *context)
614 {
615     return qp->uq_ops.qo_post_send_one_prefixed(
616             qp, dest, buf, len, flags, context);
617 }
618 
619 /*
620  * post a single-buffer send from anywhere
621  * Data is copied into registered memory by the lib for sending
622  * IN:
623  *     qp
624  *     dest
625  *     buf -
626  *     len - number of bytes in buffer, must be less than max_inline for the QP
627  * Requires 1 send credit
628  */
629 static inline int
usd_post_send_one_copy(struct usd_qp * qp,struct usd_dest * dest,const void * buf,size_t len,uint32_t flags,void * context)630 usd_post_send_one_copy(struct usd_qp *qp, struct usd_dest *dest,
631     const void *buf, size_t len, uint32_t flags, void *context)
632 {
633     return qp->uq_ops.qo_post_send_one_copy(
634             qp, dest, buf, len, flags, context);
635 }
636 
637 /*
638  * post a two-buffer send, the first buffer is a usually a header and must
639  * allow space *before* it for our header.
640  * For optimal efficieny, the first buffer should be aligned XXX
641  * Requires 2 send credits
642  */
643 int usd_post_send_two_prefixed(struct usd_qp *qp, struct usd_dest *dest,
644         const void *hdr, size_t hdr_len, const void *pkt, size_t pkt_len,
645         uint32_t flags, void *context);
646 
647 /*
648  * post a two-buffer send, the first buffer is a usually a header.
649  * The header and the packet will be both be copied into registered
650  * memory by usnic_direct and sent.
651  * Requires 2 send credits
652  */
653 static inline int
usd_post_send_two_copy(struct usd_qp * qp,struct usd_dest * dest,const void * hdr,size_t hdrlen,const void * pkt,size_t pktlen,uint32_t flags,void * context)654 usd_post_send_two_copy(struct usd_qp *qp, struct usd_dest *dest,
655     const void *hdr, size_t hdrlen, const void *pkt, size_t pktlen,
656     uint32_t flags, void *context)
657 {
658     return qp->uq_ops.qo_post_send_two_copy(
659             qp, dest, hdr, hdrlen, pkt, pktlen, flags, context);
660 }
661 
662 /*
663  * Post an N-buffer send
664  * All buffers must be in registered memory.
665  * Requires iov_count + 1 send credits
666  */
667 static inline int
usd_post_send_iov(struct usd_qp * qp,struct usd_dest * dest,const struct iovec * iov,size_t iov_count,uint32_t flags,void * context)668 usd_post_send_iov(struct usd_qp *qp, struct usd_dest *dest,
669     const struct iovec *iov, size_t iov_count, uint32_t flags,
670     void *context)
671 {
672     return qp->uq_ops.qo_post_send_iov(
673             qp, dest, iov, iov_count, flags, context);
674 }
675 
676 /****************************************************************
677  * enum-to-string utility functions (for prettyprinting)
678  ****************************************************************/
679 
680 const char *usd_link_state_str(enum usd_link_state state);
681 
682 const char *usd_completion_status_str(enum usd_completion_status cstatus);
683 
684 const char *usd_completion_type_str(enum usd_completion_type ctype);
685 
686 const char *usd_filter_type_str(enum usd_filter_type ftype);
687 
688 const char *usd_qp_transport_str(enum usd_qp_transport qpt);
689 
690 const char *usd_qp_type_str(enum usd_qp_type);
691 
692 const char *usd_qp_event_event_type_str(enum usd_device_event_type det);
693 
694 const char *usd_send_flag_sift_str(enum usd_send_flag_shift sfs);
695 
696 const char *usd_capability(enum usd_capability cap);
697 
698 const char *usd_devid_to_nicname(uint32_t vendor_id, uint32_t device_id);
699 
700 const char *usd_devid_to_pid(uint32_t vendor_id, uint32_t device_id);
701 
702 /****************************************************************
703  * special API holes punched for implementing verbs
704  ****************************************************************/
705 /* open a context, mapped to a verbs open_device call */
706 int usd_open_context(const char *dev_name, int cmd_fd,
707                         struct usd_context **ctx_o);
708 
709 int usd_close_context(struct usd_context *ctx);
710 
711 /* modify the destination UDP port in a usd_dest */
712 void usd_dest_set_udp_ports(struct usd_dest *dest, struct usd_qp *src_qp,
713         uint16_t dest_port_be);
714 
715 /* create a dest with only IP addresses set */
716 int usd_create_ip_dest(struct usd_device *dev, uint32_t dest_ip_be,
717         struct usd_dest **dest_o);
718 
719 #endif /* _USNIC_DIRECT_H_ */
720