Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
2125 lines (1816 loc) · 65.5 KB

File metadata and controls

2125 lines (1816 loc) · 65.5 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (C) 2011-2014 Matteo Landi, Luigi Rizzo
* Copyright (C) 2013-2016 Universita` di Pisa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* $FreeBSD: head/sys/dev/netmap/netmap_kern.h 238985 2012-08-02 11:59:43Z luigi $
*
* The header contains the definitions of constants and function
* prototypes used only in kernelspace.
*/
#ifndef _NET_NETMAP_KERN_H_
#define _NET_NETMAP_KERN_H_
#if defined(linux)
#if defined(CONFIG_NETMAP_VALE)
#define WITH_VALE
#endif
#if defined(CONFIG_NETMAP_PIPE)
#define WITH_PIPES
#endif
#if defined(CONFIG_NETMAP_MONITOR)
#define WITH_MONITOR
#endif
#if defined(CONFIG_NETMAP_GENERIC)
#define WITH_GENERIC
#endif
#if defined(CONFIG_NETMAP_PTNETMAP_GUEST)
#define WITH_PTNETMAP_GUEST
#endif
#if defined(CONFIG_NETMAP_PTNETMAP_HOST)
#define WITH_PTNETMAP_HOST
#endif
#if defined(CONFIG_NETMAP_SINK)
#define WITH_SINK
#endif
#elif defined (_WIN32)
#define WITH_VALE // comment out to disable VALE support
#define WITH_PIPES
#define WITH_MONITOR
#define WITH_GENERIC
#else /* neither linux nor windows */
#define WITH_VALE // comment out to disable VALE support
#define WITH_PIPES
#define WITH_MONITOR
#define WITH_GENERIC
#define WITH_PTNETMAP_HOST /* ptnetmap host support */
#define WITH_PTNETMAP_GUEST /* ptnetmap guest support */
#endif
#if defined(__FreeBSD__)
#include <sys/selinfo.h>
#define likely(x) __builtin_expect((long)!!(x), 1L)
#define unlikely(x) __builtin_expect((long)!!(x), 0L)
#define __user
#define NM_LOCK_T struct mtx /* low level spinlock, used to protect queues */
#define NM_MTX_T struct sx /* OS-specific mutex (sleepable) */
#define NM_MTX_INIT(m) sx_init(&(m), #m)
#define NM_MTX_DESTROY(m) sx_destroy(&(m))
#define NM_MTX_LOCK(m) sx_xlock(&(m))
#define NM_MTX_UNLOCK(m) sx_xunlock(&(m))
#define NM_MTX_ASSERT(m) sx_assert(&(m), SA_XLOCKED)
#define NM_SELINFO_T struct nm_selinfo
#define NM_SELRECORD_T struct thread
#define MBUF_LEN(m) ((m)->m_pkthdr.len)
#define MBUF_TXQ(m) ((m)->m_pkthdr.flowid)
#define MBUF_TRANSMIT(na, ifp, m) ((na)->if_transmit(ifp, m))
#define GEN_TX_MBUF_IFP(m) ((m)->m_pkthdr.rcvif)
#define NM_ATOMIC_T volatile int // XXX ?
/* atomic operations */
#include <machine/atomic.h>
#define NM_ATOMIC_TEST_AND_SET(p) (!atomic_cmpset_acq_int((p), 0, 1))
#define NM_ATOMIC_CLEAR(p) atomic_store_rel_int((p), 0)
#if __FreeBSD_version >= 1100030
#define WNA(_ifp) (_ifp)->if_netmap
#else /* older FreeBSD */
#define WNA(_ifp) (_ifp)->if_pspare[0]
#endif /* older FreeBSD */
#if __FreeBSD_version >= 1100005
struct netmap_adapter *netmap_getna(if_t ifp);
#endif
#if __FreeBSD_version >= 1100027
#define MBUF_REFCNT(m) ((m)->m_ext.ext_count)
#define SET_MBUF_REFCNT(m, x) (m)->m_ext.ext_count = x
#else
#define MBUF_REFCNT(m) ((m)->m_ext.ref_cnt ? *((m)->m_ext.ref_cnt) : -1)
#define SET_MBUF_REFCNT(m, x) *((m)->m_ext.ref_cnt) = x
#endif
#define MBUF_QUEUED(m) 1
struct nm_selinfo {
struct selinfo si;
struct mtx m;
};
// XXX linux struct, not used in FreeBSD
struct net_device_ops {
};
struct ethtool_ops {
};
struct hrtimer {
};
#define NM_BNS_GET(b)
#define NM_BNS_PUT(b)
#elif defined (linux)
#define NM_LOCK_T safe_spinlock_t // see bsd_glue.h
#define NM_SELINFO_T wait_queue_head_t
#define MBUF_LEN(m) ((m)->len)
#define MBUF_TRANSMIT(na, ifp, m) \
({ \
/* Avoid infinite recursion with generic. */ \
m->priority = NM_MAGIC_PRIORITY_TX; \
(((struct net_device_ops *)(na)->if_transmit)->ndo_start_xmit(m, ifp)); \
0; \
})
/* See explanation in nm_os_generic_xmit_frame. */
#define GEN_TX_MBUF_IFP(m) ((struct ifnet *)skb_shinfo(m)->destructor_arg)
#define NM_ATOMIC_T volatile long unsigned int
#define NM_MTX_T struct mutex /* OS-specific sleepable lock */
#define NM_MTX_INIT(m) mutex_init(&(m))
#define NM_MTX_DESTROY(m) do { (void)(m); } while (0)
#define NM_MTX_LOCK(m) mutex_lock(&(m))
#define NM_MTX_UNLOCK(m) mutex_unlock(&(m))
#define NM_MTX_ASSERT(m) mutex_is_locked(&(m))
#ifndef DEV_NETMAP
#define DEV_NETMAP
#endif /* DEV_NETMAP */
#elif defined (__APPLE__)
#warning apple support is incomplete.
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define NM_LOCK_T IOLock *
#define NM_SELINFO_T struct selinfo
#define MBUF_LEN(m) ((m)->m_pkthdr.len)
#elif defined (_WIN32)
#include "../../../WINDOWS/win_glue.h"
#define NM_SELRECORD_T IO_STACK_LOCATION
#define NM_SELINFO_T win_SELINFO // see win_glue.h
#define NM_LOCK_T win_spinlock_t // see win_glue.h
#define NM_MTX_T KGUARDED_MUTEX /* OS-specific mutex (sleepable) */
#define NM_MTX_INIT(m) KeInitializeGuardedMutex(&m);
#define NM_MTX_DESTROY(m) do { (void)(m); } while (0)
#define NM_MTX_LOCK(m) KeAcquireGuardedMutex(&(m))
#define NM_MTX_UNLOCK(m) KeReleaseGuardedMutex(&(m))
#define NM_MTX_ASSERT(m) assert(&m.Count>0)
//These linknames are for the NDIS driver
#define NETMAP_NDIS_LINKNAME_STRING L"\\DosDevices\\NMAPNDIS"
#define NETMAP_NDIS_NTDEVICE_STRING L"\\Device\\NMAPNDIS"
//Definition of internal driver-to-driver ioctl codes
#define NETMAP_KERNEL_XCHANGE_POINTERS _IO('i', 180)
#define NETMAP_KERNEL_SEND_SHUTDOWN_SIGNAL _IO_direct('i', 195)
//Empty data structures are not permitted by MSVC compiler
//XXX_ale, try to solve this problem
struct net_device_ops{
char data[1];
};
typedef struct ethtool_ops{
char data[1];
};
typedef struct hrtimer{
KTIMER timer;
BOOLEAN active;
KDPC deferred_proc;
};
/* MSVC does not have likely/unlikely support */
#ifdef _MSC_VER
#define likely(x) (x)
#define unlikely(x) (x)
#else
#define likely(x) __builtin_expect((long)!!(x), 1L)
#define unlikely(x) __builtin_expect((long)!!(x), 0L)
#endif //_MSC_VER
#else
#error unsupported platform
#endif /* end - platform-specific code */
#ifndef _WIN32 /* support for emulated sysctl */
#define SYSBEGIN(x)
#define SYSEND
#endif /* _WIN32 */
#define NM_ACCESS_ONCE(x) (*(volatile __typeof__(x) *)&(x))
#define NMG_LOCK_T NM_MTX_T
#define NMG_LOCK_INIT() NM_MTX_INIT(netmap_global_lock)
#define NMG_LOCK_DESTROY() NM_MTX_DESTROY(netmap_global_lock)
#define NMG_LOCK() NM_MTX_LOCK(netmap_global_lock)
#define NMG_UNLOCK() NM_MTX_UNLOCK(netmap_global_lock)
#define NMG_LOCK_ASSERT() NM_MTX_ASSERT(netmap_global_lock)
#define ND(format, ...)
#define D(format, ...) \
do { \
struct timeval __xxts; \
microtime(&__xxts); \
printf("%03d.%06d [%4d] %-25s " format "\n", \
(int)__xxts.tv_sec % 1000, (int)__xxts.tv_usec, \
__LINE__, __FUNCTION__, ##__VA_ARGS__); \
} while (0)
/* rate limited, lps indicates how many per second */
#define RD(lps, format, ...) \
do { \
static int t0, __cnt; \
if (t0 != time_second) { \
t0 = time_second; \
__cnt = 0; \
} \
if (__cnt++ < lps) \
D(format, ##__VA_ARGS__); \
} while (0)
struct netmap_adapter;
struct nm_bdg_fwd;
struct nm_bridge;
struct netmap_priv_d;
/* os-specific NM_SELINFO_T initialzation/destruction functions */
void nm_os_selinfo_init(NM_SELINFO_T *);
void nm_os_selinfo_uninit(NM_SELINFO_T *);
const char *nm_dump_buf(char *p, int len, int lim, char *dst);
void nm_os_selwakeup(NM_SELINFO_T *si);
void nm_os_selrecord(NM_SELRECORD_T *sr, NM_SELINFO_T *si);
int nm_os_ifnet_init(void);
void nm_os_ifnet_fini(void);
void nm_os_ifnet_lock(void);
void nm_os_ifnet_unlock(void);
void nm_os_get_module(void);
void nm_os_put_module(void);
void netmap_make_zombie(struct ifnet *);
void netmap_undo_zombie(struct ifnet *);
/* os independent alloc/realloc/free */
void *nm_os_malloc(size_t);
void *nm_os_realloc(void *, size_t new_size, size_t old_size);
void nm_os_free(void *);
/* passes a packet up to the host stack.
* If the packet is sent (or dropped) immediately it returns NULL,
* otherwise it links the packet to prev and returns m.
* In this case, a final call with m=NULL and prev != NULL will send up
* the entire chain to the host stack.
*/
void *nm_os_send_up(struct ifnet *, struct mbuf *m, struct mbuf *prev);
int nm_os_mbuf_has_offld(struct mbuf *m);
#include "netmap_mbq.h"
extern NMG_LOCK_T netmap_global_lock;
enum txrx { NR_RX = 0, NR_TX = 1, NR_TXRX };
static __inline const char*
nm_txrx2str(enum txrx t)
{
return (t== NR_RX ? "RX" : "TX");
}
static __inline enum txrx
nm_txrx_swap(enum txrx t)
{
return (t== NR_RX ? NR_TX : NR_RX);
}
#define for_rx_tx(t) for ((t) = 0; (t) < NR_TXRX; (t)++)
#ifdef WITH_MONITOR
struct netmap_zmon_list {
struct netmap_kring *next;
struct netmap_kring *prev;
};
#endif /* WITH_MONITOR */
/*
* private, kernel view of a ring. Keeps track of the status of
* a ring across system calls.
*
* nr_hwcur index of the next buffer to refill.
* It corresponds to ring->head
* at the time the system call returns.
*
* nr_hwtail index of the first buffer owned by the kernel.
* On RX, hwcur->hwtail are receive buffers
* not yet released. hwcur is advanced following
* ring->head, hwtail is advanced on incoming packets,
* and a wakeup is generated when hwtail passes ring->cur
* On TX, hwcur->rcur have been filled by the sender
* but not sent yet to the NIC; rcur->hwtail are available
* for new transmissions, and hwtail->hwcur-1 are pending
* transmissions not yet acknowledged.
*
* The indexes in the NIC and netmap rings are offset by nkr_hwofs slots.
* This is so that, on a reset, buffers owned by userspace are not
* modified by the kernel. In particular:
* RX rings: the next empty buffer (hwtail + hwofs) coincides with
* the next empty buffer as known by the hardware (next_to_check or so).
* TX rings: hwcur + hwofs coincides with next_to_send
*
* For received packets, slot->flags is set to nkr_slot_flags
* so we can provide a proper initial value (e.g. set NS_FORWARD
* when operating in 'transparent' mode).
*
* The following fields are used to implement lock-free copy of packets
* from input to output ports in VALE switch:
* nkr_hwlease buffer after the last one being copied.
* A writer in nm_bdg_flush reserves N buffers
* from nr_hwlease, advances it, then does the
* copy outside the lock.
* In RX rings (used for VALE ports),
* nkr_hwtail <= nkr_hwlease < nkr_hwcur+N-1
* In TX rings (used for NIC or host stack ports)
* nkr_hwcur <= nkr_hwlease < nkr_hwtail
* nkr_leases array of nkr_num_slots where writers can report
* completion of their block. NR_NOSLOT (~0) indicates
* that the writer has not finished yet
* nkr_lease_idx index of next free slot in nr_leases, to be assigned
*
* The kring is manipulated by txsync/rxsync and generic netmap function.
*
* Concurrent rxsync or txsync on the same ring are prevented through
* by nm_kr_(try)lock() which in turn uses nr_busy. This is all we need
* for NIC rings, and for TX rings attached to the host stack.
*
* RX rings attached to the host stack use an mbq (rx_queue) on both
* rxsync_from_host() and netmap_transmit(). The mbq is protected
* by its internal lock.
*
* RX rings attached to the VALE switch are accessed by both senders
* and receiver. They are protected through the q_lock on the RX ring.
*/
struct netmap_kring {
struct netmap_ring *ring;
uint32_t nr_hwcur;
uint32_t nr_hwtail;
/*
* Copies of values in user rings, so we do not need to look
* at the ring (which could be modified). These are set in the
* *sync_prologue()/finalize() routines.
*/
uint32_t rhead;
uint32_t rcur;
uint32_t rtail;
uint32_t nr_kflags; /* private driver flags */
#define NKR_PENDINTR 0x1 // Pending interrupt.
#define NKR_EXCLUSIVE 0x2 /* exclusive binding */
#define NKR_FORWARD 0x4 /* (host ring only) there are
packets to forward
*/
#define NKR_NEEDRING 0x8 /* ring needed even if users==0
* (used internally by pipes and
* by ptnetmap host ports)
*/
uint32_t nr_mode;
uint32_t nr_pending_mode;
#define NKR_NETMAP_OFF 0x0
#define NKR_NETMAP_ON 0x1
uint32_t nkr_num_slots;
/*
* On a NIC reset, the NIC ring indexes may be reset but the
* indexes in the netmap rings remain the same. nkr_hwofs
* keeps track of the offset between the two.
*/
int32_t nkr_hwofs;
uint16_t nkr_slot_flags; /* initial value for flags */
/* last_reclaim is opaque marker to help reduce the frequency
* of operations such as reclaiming tx buffers. A possible use
* is set it to ticks and do the reclaim only once per tick.
*/
uint64_t last_reclaim;
NM_SELINFO_T si; /* poll/select wait queue */
NM_LOCK_T q_lock; /* protects kring and ring. */
NM_ATOMIC_T nr_busy; /* prevent concurrent syscalls */
struct netmap_adapter *na;
/* The following fields are for VALE switch support */
struct nm_bdg_fwd *nkr_ft;
uint32_t *nkr_leases;
#define NR_NOSLOT ((uint32_t)~0) /* used in nkr_*lease* */
uint32_t nkr_hwlease;
uint32_t nkr_lease_idx;
/* while nkr_stopped is set, no new [tr]xsync operations can
* be started on this kring.
* This is used by netmap_disable_all_rings()
* to find a synchronization point where critical data
* structures pointed to by the kring can be added or removed
*/
volatile int nkr_stopped;
/* Support for adapters without native netmap support.
* On tx rings we preallocate an array of tx buffers
* (same size as the netmap ring), on rx rings we
* store incoming mbufs in a queue that is drained by
* a rxsync.
*/
struct mbuf **tx_pool;
struct mbuf *tx_event; /* TX event used as a notification */
NM_LOCK_T tx_event_lock; /* protects the tx_event mbuf */
struct mbq rx_queue; /* intercepted rx mbufs. */
uint32_t users; /* existing bindings for this ring */
uint32_t ring_id; /* kring identifier */
enum txrx tx; /* kind of ring (tx or rx) */
char name[64]; /* diagnostic */
/* [tx]sync callback for this kring.
* The default nm_kring_create callback (netmap_krings_create)
* sets the nm_sync callback of each hardware tx(rx) kring to
* the corresponding nm_txsync(nm_rxsync) taken from the
* netmap_adapter; moreover, it sets the sync callback
* of the host tx(rx) ring to netmap_txsync_to_host
* (netmap_rxsync_from_host).
*
* Overrides: the above configuration is not changed by
* any of the nm_krings_create callbacks.
*/
int (*nm_sync)(struct netmap_kring *kring, int flags);
int (*nm_notify)(struct netmap_kring *kring, int flags);
#ifdef WITH_PIPES
struct netmap_kring *pipe; /* if this is a pipe ring,
* pointer to the other end
*/
#endif /* WITH_PIPES */
#ifdef WITH_VALE
int (*save_notify)(struct netmap_kring *kring, int flags);
#endif
#ifdef WITH_MONITOR
/* array of krings that are monitoring this kring */
struct netmap_kring **monitors;
uint32_t max_monitors; /* current size of the monitors array */
uint32_t n_monitors; /* next unused entry in the monitor array */
uint32_t mon_pos[NR_TXRX]; /* index of this ring in the monitored ring array */
uint32_t mon_tail; /* last seen slot on rx */
/* circular list of zero-copy monitors */
struct netmap_zmon_list zmon_list[NR_TXRX];
/*
* Monitors work by intercepting the sync and notify callbacks of the
* monitored krings. This is implemented by replacing the pointers
* above and saving the previous ones in mon_* pointers below
*/
int (*mon_sync)(struct netmap_kring *kring, int flags);
int (*mon_notify)(struct netmap_kring *kring, int flags);
#endif
}
#ifdef _WIN32
__declspec(align(64));
#else
__attribute__((__aligned__(64)));
#endif
/* return 1 iff the kring needs to be turned on */
static inline int
nm_kring_pending_on(struct netmap_kring *kring)
{
return kring->nr_pending_mode == NKR_NETMAP_ON &&
kring->nr_mode == NKR_NETMAP_OFF;
}
/* return 1 iff the kring needs to be turned off */
static inline int
nm_kring_pending_off(struct netmap_kring *kring)
{
return kring->nr_pending_mode == NKR_NETMAP_OFF &&
kring->nr_mode == NKR_NETMAP_ON;
}
/* return the next index, with wraparound */
static inline uint32_t
nm_next(uint32_t i, uint32_t lim)
{
return unlikely (i == lim) ? 0 : i + 1;
}
/* return the previous index, with wraparound */
static inline uint32_t
nm_prev(uint32_t i, uint32_t lim)
{
return unlikely (i == 0) ? lim : i - 1;
}
/*
*
* Here is the layout for the Rx and Tx rings.
RxRING TxRING
+-----------------+ +-----------------+
| | | |
|XXX free slot XXX| |XXX free slot XXX|
+-----------------+ +-----------------+
head->| owned by user |<-hwcur | not sent to nic |<-hwcur
| | | yet |
+-----------------+ | |
cur->| available to | | |
| user, not read | +-----------------+
| yet | cur->| (being |
| | | prepared) |
| | | |
+-----------------+ + ------ +
tail->| |<-hwtail | |<-hwlease
| (being | ... | | ...
| prepared) | ... | | ...
+-----------------+ ... | | ...
| |<-hwlease +-----------------+
| | tail->| |<-hwtail
| | | |
| | | |
| | | |
+-----------------+ +-----------------+
* The cur/tail (user view) and hwcur/hwtail (kernel view)
* are used in the normal operation of the card.
*
* When a ring is the output of a switch port (Rx ring for
* a VALE port, Tx ring for the host stack or NIC), slots
* are reserved in blocks through 'hwlease' which points
* to the next unused slot.
* On an Rx ring, hwlease is always after hwtail,
* and completions cause hwtail to advance.
* On a Tx ring, hwlease is always between cur and hwtail,
* and completions cause cur to advance.
*
* nm_kr_space() returns the maximum number of slots that
* can be assigned.
* nm_kr_lease() reserves the required number of buffers,
* advances nkr_hwlease and also returns an entry in
* a circular array where completions should be reported.
*/
struct netmap_lut {
struct lut_entry *lut;
uint32_t objtotal; /* max buffer index */
uint32_t objsize; /* buffer size */
};
struct netmap_vp_adapter; // forward
/*
* The "struct netmap_adapter" extends the "struct adapter"
* (or equivalent) device descriptor.
* It contains all base fields needed to support netmap operation.
* There are in fact different types of netmap adapters
* (native, generic, VALE switch...) so a netmap_adapter is
* just the first field in the derived type.
*/
struct netmap_adapter {
/*
* On linux we do not have a good way to tell if an interface
* is netmap-capable. So we always use the following trick:
* NA(ifp) points here, and the first entry (which hopefully
* always exists and is at least 32 bits) contains a magic
* value which we can use to detect that the interface is good.
*/
uint32_t magic;
uint32_t na_flags; /* enabled, and other flags */
#define NAF_SKIP_INTR 1 /* use the regular interrupt handler.
* useful during initialization
*/
#define NAF_SW_ONLY 2 /* forward packets only to sw adapter */
#define NAF_BDG_MAYSLEEP 4 /* the bridge is allowed to sleep when
* forwarding packets coming from this
* interface
*/
#define NAF_MEM_OWNER 8 /* the adapter uses its own memory area
* that cannot be changed
*/
#define NAF_NATIVE 16 /* the adapter is native.
* Virtual ports (non persistent vale ports,
* pipes, monitors...) should never use
* this flag.
*/
#define NAF_NETMAP_ON 32 /* netmap is active (either native or
* emulated). Where possible (e.g. FreeBSD)
* IFCAP_NETMAP also mirrors this flag.
*/
#define NAF_HOST_RINGS 64 /* the adapter supports the host rings */
#define NAF_FORCE_NATIVE 128 /* the adapter is always NATIVE */
#define NAF_PTNETMAP_HOST 256 /* the adapter supports ptnetmap in the host */
#define NAF_ZOMBIE (1U<<30) /* the nic driver has been unloaded */
#define NAF_BUSY (1U<<31) /* the adapter is used internally and
* cannot be registered from userspace
*/
int active_fds; /* number of user-space descriptors using this
interface, which is equal to the number of
struct netmap_if objs in the mapped region. */
u_int num_rx_rings; /* number of adapter receive rings */
u_int num_tx_rings; /* number of adapter transmit rings */
u_int num_tx_desc; /* number of descriptor in each queue */
u_int num_rx_desc;
/* tx_rings and rx_rings are private but allocated
* as a contiguous chunk of memory. Each array has
* N+1 entries, for the adapter queues and for the host queue.
*/
struct netmap_kring *tx_rings; /* array of TX rings. */
struct netmap_kring *rx_rings; /* array of RX rings. */
void *tailroom; /* space below the rings array */
/* (used for leases) */
NM_SELINFO_T si[NR_TXRX]; /* global wait queues */
/* count users of the global wait queues */
int si_users[NR_TXRX];
void *pdev; /* used to store pci device */
/* copy of if_qflush and if_transmit pointers, to intercept
* packets from the network stack when netmap is active.
*/
int (*if_transmit)(struct ifnet *, struct mbuf *);
/* copy of if_input for netmap_send_up() */
void (*if_input)(struct ifnet *, struct mbuf *);
/* references to the ifnet and device routines, used by
* the generic netmap functions.
*/
struct ifnet *ifp; /* adapter is ifp->if_softc */
/*---- callbacks for this netmap adapter -----*/
/*
* nm_dtor() is the cleanup routine called when destroying
* the adapter.
* Called with NMG_LOCK held.
*
* nm_register() is called on NIOCREGIF and close() to enter
* or exit netmap mode on the NIC
* Called with NNG_LOCK held.
*
* nm_txsync() pushes packets to the underlying hw/switch
*
* nm_rxsync() collects packets from the underlying hw/switch
*
* nm_config() returns configuration information from the OS
* Called with NMG_LOCK held.
*
* nm_krings_create() create and init the tx_rings and
* rx_rings arrays of kring structures. In particular,
* set the nm_sync callbacks for each ring.
* There is no need to also allocate the corresponding
* netmap_rings, since netmap_mem_rings_create() will always
* be called to provide the missing ones.
* Called with NNG_LOCK held.
*
* nm_krings_delete() cleanup and delete the tx_rings and rx_rings
* arrays
* Called with NMG_LOCK held.
*
* nm_notify() is used to act after data have become available
* (or the stopped state of the ring has changed)
* For hw devices this is typically a selwakeup(),
* but for NIC/host ports attached to a switch (or vice-versa)
* we also need to invoke the 'txsync' code downstream.
* This callback pointer is actually used only to initialize
* kring->nm_notify.
* Return values are the same as for netmap_rx_irq().
*/
void (*nm_dtor)(struct netmap_adapter *);
int (*nm_register)(struct netmap_adapter *, int onoff);
void (*nm_intr)(struct netmap_adapter *, int onoff);
int (*nm_txsync)(struct netmap_kring *kring, int flags);
int (*nm_rxsync)(struct netmap_kring *kring, int flags);
int (*nm_notify)(struct netmap_kring *kring, int flags);
#define NAF_FORCE_READ 1
#define NAF_FORCE_RECLAIM 2
#define NAF_CAN_FORWARD_DOWN 4
/* return configuration information */
int (*nm_config)(struct netmap_adapter *,
u_int *txr, u_int *txd, u_int *rxr, u_int *rxd);
int (*nm_krings_create)(struct netmap_adapter *);
void (*nm_krings_delete)(struct netmap_adapter *);
#ifdef WITH_VALE
/*
* nm_bdg_attach() initializes the na_vp field to point
* to an adapter that can be attached to a VALE switch. If the
* current adapter is already a VALE port, na_vp is simply a cast;
* otherwise, na_vp points to a netmap_bwrap_adapter.
* If applicable, this callback also initializes na_hostvp,
* that can be used to connect the adapter host rings to the
* switch.
* Called with NMG_LOCK held.
*
* nm_bdg_ctl() is called on the actual attach/detach to/from
* to/from the switch, to perform adapter-specific
* initializations
* Called with NMG_LOCK held.
*/
int (*nm_bdg_attach)(const char *bdg_name, struct netmap_adapter *);
int (*nm_bdg_ctl)(struct netmap_adapter *, struct nmreq *, int);
/* adapter used to attach this adapter to a VALE switch (if any) */
struct netmap_vp_adapter *na_vp;
/* adapter used to attach the host rings of this adapter
* to a VALE switch (if any) */
struct netmap_vp_adapter *na_hostvp;
#endif
/* standard refcount to control the lifetime of the adapter
* (it should be equal to the lifetime of the corresponding ifp)
*/
int na_refcount;
/* memory allocator (opaque)
* We also cache a pointer to the lut_entry for translating
* buffer addresses, the total number of buffers and the buffer size.
*/
struct netmap_mem_d *nm_mem;
struct netmap_lut na_lut;
/* additional information attached to this adapter
* by other netmap subsystems. Currently used by
* bwrap, LINUX/v1000 and ptnetmap
*/
void *na_private;
/* array of pipes that have this adapter as a parent */
struct netmap_pipe_adapter **na_pipes;
int na_next_pipe; /* next free slot in the array */
int na_max_pipes; /* size of the array */
/* Offset of ethernet header for each packet. */
u_int virt_hdr_len;
char name[64];
};
static __inline u_int
nma_get_ndesc(struct netmap_adapter *na, enum txrx t)
{
return (t == NR_TX ? na->num_tx_desc : na->num_rx_desc);
}
static __inline void
nma_set_ndesc(struct netmap_adapter *na, enum txrx t, u_int v)
{
if (t == NR_TX)
na->num_tx_desc = v;
else
na->num_rx_desc = v;
}
static __inline u_int
nma_get_nrings(struct netmap_adapter *na, enum txrx t)
{
return (t == NR_TX ? na->num_tx_rings : na->num_rx_rings);
}
static __inline void
nma_set_nrings(struct netmap_adapter *na, enum txrx t, u_int v)
{
if (t == NR_TX)
na->num_tx_rings = v;
else
na->num_rx_rings = v;
}
static __inline struct netmap_kring*
NMR(struct netmap_adapter *na, enum txrx t)
{
return (t == NR_TX ? na->tx_rings : na->rx_rings);
}
/*
* If the NIC is owned by the kernel
* (i.e., bridge), neither another bridge nor user can use it;
* if the NIC is owned by a user, only users can share it.
* Evaluation must be done under NMG_LOCK().
*/
#define NETMAP_OWNED_BY_KERN(na) ((na)->na_flags & NAF_BUSY)
#define NETMAP_OWNED_BY_ANY(na) \
(NETMAP_OWNED_BY_KERN(na) || ((na)->active_fds > 0))
/*
* derived netmap adapters for various types of ports
*/
struct netmap_vp_adapter { /* VALE software port */
struct netmap_adapter up;
/*
* Bridge support:
*
* bdg_port is the port number used in the bridge;
* na_bdg points to the bridge this NA is attached to.
*/
int bdg_port;
struct nm_bridge *na_bdg;
int retry;
int autodelete; /* remove the ifp on last reference */
/* Maximum Frame Size, used in bdg_mismatch_datapath() */
u_int mfs;
/* Last source MAC on this port */
uint64_t last_smac;
};
struct netmap_hw_adapter { /* physical device */
struct netmap_adapter up;
struct net_device_ops nm_ndo; // XXX linux only
struct ethtool_ops nm_eto; // XXX linux only
const struct ethtool_ops* save_ethtool;
int (*nm_hw_register)(struct netmap_adapter *, int onoff);
};
#ifdef WITH_GENERIC
/* Mitigation support. */
struct nm_generic_mit {
struct hrtimer mit_timer;
int mit_pending;
int mit_ring_idx; /* index of the ring being mitigated */
struct netmap_adapter *mit_na; /* backpointer */
};
struct netmap_generic_adapter { /* emulated device */
struct netmap_hw_adapter up;
/* Pointer to a previously used netmap adapter. */
struct netmap_adapter *prev;
/* generic netmap adapters support:
* a net_device_ops struct overrides ndo_select_queue(),
* save_if_input saves the if_input hook (FreeBSD),
* mit implements rx interrupt mitigation,
*/
struct net_device_ops generic_ndo;
void (*save_if_input)(struct ifnet *, struct mbuf *);
struct nm_generic_mit *mit;
#ifdef linux
netdev_tx_t (*save_start_xmit)(struct mbuf *, struct ifnet *);
#endif
/* Is the adapter able to use multiple RX slots to scatter
* each packet pushed up by the driver? */
int rxsg;
/* Is the transmission path controlled by a netmap-aware
* device queue (i.e. qdisc on linux)? */
int txqdisc;
};
#endif /* WITH_GENERIC */
static __inline int
netmap_real_rings(struct netmap_adapter *na, enum txrx t)
{
return nma_get_nrings(na, t) + !!(na->na_flags & NAF_HOST_RINGS);
}
#ifdef WITH_VALE
struct nm_bdg_polling_state;
/*
* Bridge wrapper for non VALE ports attached to a VALE switch.
*
* The real device must already have its own netmap adapter (hwna).
* The bridge wrapper and the hwna adapter share the same set of
* netmap rings and buffers, but they have two separate sets of
* krings descriptors, with tx/rx meanings swapped:
*
* netmap
* bwrap krings rings krings hwna
* +------+ +------+ +-----+ +------+ +------+
* |tx_rings->| |\ /| |----| |<-tx_rings|
* | | +------+ \ / +-----+ +------+ | |
* | | X | |
* | | / \ | |
* | | +------+/ \+-----+ +------+ | |
* |rx_rings->| | | |----| |<-rx_rings|
* | | +------+ +-----+ +------+ | |
* +------+ +------+
*
* - packets coming from the bridge go to the brwap rx rings,
* which are also the hwna tx rings. The bwrap notify callback
* will then complete the hwna tx (see netmap_bwrap_notify).
*
* - packets coming from the outside go to the hwna rx rings,
* which are also the bwrap tx rings. The (overwritten) hwna
* notify method will then complete the bridge tx
* (see netmap_bwrap_intr_notify).
*
* The bridge wrapper may optionally connect the hwna 'host' rings
* to the bridge. This is done by using a second port in the
* bridge and connecting it to the 'host' netmap_vp_adapter
* contained in the netmap_bwrap_adapter. The brwap host adapter
* cross-links the hwna host rings in the same way as shown above.
*
* - packets coming from the bridge and directed to the host stack
* are handled by the bwrap host notify callback
* (see netmap_bwrap_host_notify)
*
* - packets coming from the host stack are still handled by the
* overwritten hwna notify callback (netmap_bwrap_intr_notify),
* but are diverted to the host adapter depending on the ring number.
*
*/
struct netmap_bwrap_adapter {
struct netmap_vp_adapter up;
struct netmap_vp_adapter host; /* for host rings */
struct netmap_adapter *hwna; /* the underlying device */
/*
* When we attach a physical interface to the bridge, we
* allow the controlling process to terminate, so we need
* a place to store the n_detmap_priv_d data structure.
* This is only done when physical interfaces
* are attached to a bridge.
*/
struct netmap_priv_d *na_kpriv;
struct nm_bdg_polling_state *na_polling_state;
};
int netmap_bwrap_attach(const char *name, struct netmap_adapter *);
int netmap_vi_create(struct nmreq *, int);
Morty Proxy This is a proxified and sanitized view of the page, visit original site.