diff options
Diffstat (limited to 'Documentation/networking')
-rw-r--r-- | Documentation/networking/ieee802154.txt | 5 | ||||
-rw-r--r-- | Documentation/networking/ip-sysctl.txt | 53 | ||||
-rw-r--r-- | Documentation/networking/netlink_mmap.txt | 339 | ||||
-rw-r--r-- | Documentation/networking/packet_mmap.txt | 368 | ||||
-rw-r--r-- | Documentation/networking/stmmac.txt | 45 |
5 files changed, 756 insertions, 54 deletions
diff --git a/Documentation/networking/ieee802154.txt b/Documentation/networking/ieee802154.txt index 703cf4370c79..67a9cb259d40 100644 --- a/Documentation/networking/ieee802154.txt +++ b/Documentation/networking/ieee802154.txt | |||
@@ -71,8 +71,9 @@ submits skb to qdisc), so if you need something from that cb later, you should | |||
71 | store info in the skb->data on your own. | 71 | store info in the skb->data on your own. |
72 | 72 | ||
73 | To hook the MLME interface you have to populate the ml_priv field of your | 73 | To hook the MLME interface you have to populate the ml_priv field of your |
74 | net_device with a pointer to struct ieee802154_mlme_ops instance. All fields are | 74 | net_device with a pointer to struct ieee802154_mlme_ops instance. The fields |
75 | required. | 75 | assoc_req, assoc_resp, disassoc_req, start_req, and scan_req are optional. |
76 | All other fields are required. | ||
76 | 77 | ||
77 | We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c | 78 | We provide an example of simple HardMAC driver at drivers/ieee802154/fakehard.c |
78 | 79 | ||
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index dc2dc87d2557..f98ca633b528 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt | |||
@@ -29,7 +29,7 @@ route/max_size - INTEGER | |||
29 | neigh/default/gc_thresh1 - INTEGER | 29 | neigh/default/gc_thresh1 - INTEGER |
30 | Minimum number of entries to keep. Garbage collector will not | 30 | Minimum number of entries to keep. Garbage collector will not |
31 | purge entries if there are fewer than this number. | 31 | purge entries if there are fewer than this number. |
32 | Default: 256 | 32 | Default: 128 |
33 | 33 | ||
34 | neigh/default/gc_thresh3 - INTEGER | 34 | neigh/default/gc_thresh3 - INTEGER |
35 | Maximum number of neighbor entries allowed. Increase this | 35 | Maximum number of neighbor entries allowed. Increase this |
@@ -175,14 +175,6 @@ tcp_congestion_control - STRING | |||
175 | is inherited. | 175 | is inherited. |
176 | [see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ] | 176 | [see setsockopt(listenfd, SOL_TCP, TCP_CONGESTION, "name" ...) ] |
177 | 177 | ||
178 | tcp_cookie_size - INTEGER | ||
179 | Default size of TCP Cookie Transactions (TCPCT) option, that may be | ||
180 | overridden on a per socket basis by the TCPCT socket option. | ||
181 | Values greater than the maximum (16) are interpreted as the maximum. | ||
182 | Values greater than zero and less than the minimum (8) are interpreted | ||
183 | as the minimum. Odd values are interpreted as the next even value. | ||
184 | Default: 0 (off). | ||
185 | |||
186 | tcp_dsack - BOOLEAN | 178 | tcp_dsack - BOOLEAN |
187 | Allows TCP to send "duplicate" SACKs. | 179 | Allows TCP to send "duplicate" SACKs. |
188 | 180 | ||
@@ -190,7 +182,9 @@ tcp_early_retrans - INTEGER | |||
190 | Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold | 182 | Enable Early Retransmit (ER), per RFC 5827. ER lowers the threshold |
191 | for triggering fast retransmit when the amount of outstanding data is | 183 | for triggering fast retransmit when the amount of outstanding data is |
192 | small and when no previously unsent data can be transmitted (such | 184 | small and when no previously unsent data can be transmitted (such |
193 | that limited transmit could be used). | 185 | that limited transmit could be used). Also controls the use of |
186 | Tail loss probe (TLP) that converts RTOs occuring due to tail | ||
187 | losses into fast recovery (draft-dukkipati-tcpm-tcp-loss-probe-01). | ||
194 | Possible values: | 188 | Possible values: |
195 | 0 disables ER | 189 | 0 disables ER |
196 | 1 enables ER | 190 | 1 enables ER |
@@ -198,7 +192,9 @@ tcp_early_retrans - INTEGER | |||
198 | by a fourth of RTT. This mitigates connection falsely | 192 | by a fourth of RTT. This mitigates connection falsely |
199 | recovers when network has a small degree of reordering | 193 | recovers when network has a small degree of reordering |
200 | (less than 3 packets). | 194 | (less than 3 packets). |
201 | Default: 2 | 195 | 3 enables delayed ER and TLP. |
196 | 4 enables TLP only. | ||
197 | Default: 3 | ||
202 | 198 | ||
203 | tcp_ecn - INTEGER | 199 | tcp_ecn - INTEGER |
204 | Control use of Explicit Congestion Notification (ECN) by TCP. | 200 | Control use of Explicit Congestion Notification (ECN) by TCP. |
@@ -229,36 +225,13 @@ tcp_fin_timeout - INTEGER | |||
229 | Default: 60 seconds | 225 | Default: 60 seconds |
230 | 226 | ||
231 | tcp_frto - INTEGER | 227 | tcp_frto - INTEGER |
232 | Enables Forward RTO-Recovery (F-RTO) defined in RFC4138. | 228 | Enables Forward RTO-Recovery (F-RTO) defined in RFC5682. |
233 | F-RTO is an enhanced recovery algorithm for TCP retransmission | 229 | F-RTO is an enhanced recovery algorithm for TCP retransmission |
234 | timeouts. It is particularly beneficial in wireless environments | 230 | timeouts. It is particularly beneficial in networks where the |
235 | where packet loss is typically due to random radio interference | 231 | RTT fluctuates (e.g., wireless). F-RTO is sender-side only |
236 | rather than intermediate router congestion. F-RTO is sender-side | 232 | modification. It does not require any support from the peer. |
237 | only modification. Therefore it does not require any support from | 233 | |
238 | the peer. | 234 | By default it's enabled with a non-zero value. 0 disables F-RTO. |
239 | |||
240 | If set to 1, basic version is enabled. 2 enables SACK enhanced | ||
241 | F-RTO if flow uses SACK. The basic version can be used also when | ||
242 | SACK is in use though scenario(s) with it exists where F-RTO | ||
243 | interacts badly with the packet counting of the SACK enabled TCP | ||
244 | flow. | ||
245 | |||
246 | tcp_frto_response - INTEGER | ||
247 | When F-RTO has detected that a TCP retransmission timeout was | ||
248 | spurious (i.e, the timeout would have been avoided had TCP set a | ||
249 | longer retransmission timeout), TCP has several options what to do | ||
250 | next. Possible values are: | ||
251 | 0 Rate halving based; a smooth and conservative response, | ||
252 | results in halved cwnd and ssthresh after one RTT | ||
253 | 1 Very conservative response; not recommended because even | ||
254 | though being valid, it interacts poorly with the rest of | ||
255 | Linux TCP, halves cwnd and ssthresh immediately | ||
256 | 2 Aggressive response; undoes congestion control measures | ||
257 | that are now known to be unnecessary (ignoring the | ||
258 | possibility of a lost retransmission that would require | ||
259 | TCP to be more cautious), cwnd and ssthresh are restored | ||
260 | to the values prior timeout | ||
261 | Default: 0 (rate halving based) | ||
262 | 235 | ||
263 | tcp_keepalive_time - INTEGER | 236 | tcp_keepalive_time - INTEGER |
264 | How often TCP sends out keepalive messages when keepalive is enabled. | 237 | How often TCP sends out keepalive messages when keepalive is enabled. |
diff --git a/Documentation/networking/netlink_mmap.txt b/Documentation/networking/netlink_mmap.txt new file mode 100644 index 000000000000..1c2dab409625 --- /dev/null +++ b/Documentation/networking/netlink_mmap.txt | |||
@@ -0,0 +1,339 @@ | |||
1 | This file documents how to use memory mapped I/O with netlink. | ||
2 | |||
3 | Author: Patrick McHardy <kaber@trash.net> | ||
4 | |||
5 | Overview | ||
6 | -------- | ||
7 | |||
8 | Memory mapped netlink I/O can be used to increase throughput and decrease | ||
9 | overhead of unicast receive and transmit operations. Some netlink subsystems | ||
10 | require high throughput, these are mainly the netfilter subsystems | ||
11 | nfnetlink_queue and nfnetlink_log, but it can also help speed up large | ||
12 | dump operations of f.i. the routing database. | ||
13 | |||
14 | Memory mapped netlink I/O used two circular ring buffers for RX and TX which | ||
15 | are mapped into the processes address space. | ||
16 | |||
17 | The RX ring is used by the kernel to directly construct netlink messages into | ||
18 | user-space memory without copying them as done with regular socket I/O, | ||
19 | additionally as long as the ring contains messages no recvmsg() or poll() | ||
20 | syscalls have to be issued by user-space to get more message. | ||
21 | |||
22 | The TX ring is used to process messages directly from user-space memory, the | ||
23 | kernel processes all messages contained in the ring using a single sendmsg() | ||
24 | call. | ||
25 | |||
26 | Usage overview | ||
27 | -------------- | ||
28 | |||
29 | In order to use memory mapped netlink I/O, user-space needs three main changes: | ||
30 | |||
31 | - ring setup | ||
32 | - conversion of the RX path to get messages from the ring instead of recvmsg() | ||
33 | - conversion of the TX path to construct messages into the ring | ||
34 | |||
35 | Ring setup is done using setsockopt() to provide the ring parameters to the | ||
36 | kernel, then a call to mmap() to map the ring into the processes address space: | ||
37 | |||
38 | - setsockopt(fd, SOL_NETLINK, NETLINK_RX_RING, ¶ms, sizeof(params)); | ||
39 | - setsockopt(fd, SOL_NETLINK, NETLINK_TX_RING, ¶ms, sizeof(params)); | ||
40 | - ring = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) | ||
41 | |||
42 | Usage of either ring is optional, but even if only the RX ring is used the | ||
43 | mapping still needs to be writable in order to update the frame status after | ||
44 | processing. | ||
45 | |||
46 | Conversion of the reception path involves calling poll() on the file | ||
47 | descriptor, once the socket is readable the frames from the ring are | ||
48 | processsed in order until no more messages are available, as indicated by | ||
49 | a status word in the frame header. | ||
50 | |||
51 | On kernel side, in order to make use of memory mapped I/O on receive, the | ||
52 | originating netlink subsystem needs to support memory mapped I/O, otherwise | ||
53 | it will use an allocated socket buffer as usual and the contents will be | ||
54 | copied to the ring on transmission, nullifying most of the performance gains. | ||
55 | Dumps of kernel databases automatically support memory mapped I/O. | ||
56 | |||
57 | Conversion of the transmit path involves changing message contruction to | ||
58 | use memory from the TX ring instead of (usually) a buffer declared on the | ||
59 | stack and setting up the frame header approriately. Optionally poll() can | ||
60 | be used to wait for free frames in the TX ring. | ||
61 | |||
62 | Structured and definitions for using memory mapped I/O are contained in | ||
63 | <linux/netlink.h>. | ||
64 | |||
65 | RX and TX rings | ||
66 | ---------------- | ||
67 | |||
68 | Each ring contains a number of continous memory blocks, containing frames of | ||
69 | fixed size dependant on the parameters used for ring setup. | ||
70 | |||
71 | Ring: [ block 0 ] | ||
72 | [ frame 0 ] | ||
73 | [ frame 1 ] | ||
74 | [ block 1 ] | ||
75 | [ frame 2 ] | ||
76 | [ frame 3 ] | ||
77 | ... | ||
78 | [ block n ] | ||
79 | [ frame 2 * n ] | ||
80 | [ frame 2 * n + 1 ] | ||
81 | |||
82 | The blocks are only visible to the kernel, from the point of view of user-space | ||
83 | the ring just contains the frames in a continous memory zone. | ||
84 | |||
85 | The ring parameters used for setting up the ring are defined as follows: | ||
86 | |||
87 | struct nl_mmap_req { | ||
88 | unsigned int nm_block_size; | ||
89 | unsigned int nm_block_nr; | ||
90 | unsigned int nm_frame_size; | ||
91 | unsigned int nm_frame_nr; | ||
92 | }; | ||
93 | |||
94 | Frames are grouped into blocks, where each block is a continous region of memory | ||
95 | and holds nm_block_size / nm_frame_size frames. The total number of frames in | ||
96 | the ring is nm_frame_nr. The following invariants hold: | ||
97 | |||
98 | - frames_per_block = nm_block_size / nm_frame_size | ||
99 | |||
100 | - nm_frame_nr = frames_per_block * nm_block_nr | ||
101 | |||
102 | Some parameters are constrained, specifically: | ||
103 | |||
104 | - nm_block_size must be a multiple of the architectures memory page size. | ||
105 | The getpagesize() function can be used to get the page size. | ||
106 | |||
107 | - nm_frame_size must be equal or larger to NL_MMAP_HDRLEN, IOW a frame must be | ||
108 | able to hold at least the frame header | ||
109 | |||
110 | - nm_frame_size must be smaller or equal to nm_block_size | ||
111 | |||
112 | - nm_frame_size must be a multiple of NL_MMAP_MSG_ALIGNMENT | ||
113 | |||
114 | - nm_frame_nr must equal the actual number of frames as specified above. | ||
115 | |||
116 | When the kernel can't allocate phsyically continous memory for a ring block, | ||
117 | it will fall back to use physically discontinous memory. This might affect | ||
118 | performance negatively, in order to avoid this the nm_frame_size parameter | ||
119 | should be chosen to be as small as possible for the required frame size and | ||
120 | the number of blocks should be increased instead. | ||
121 | |||
122 | Ring frames | ||
123 | ------------ | ||
124 | |||
125 | Each frames contain a frame header, consisting of a synchronization word and some | ||
126 | meta-data, and the message itself. | ||
127 | |||
128 | Frame: [ header message ] | ||
129 | |||
130 | The frame header is defined as follows: | ||
131 | |||
132 | struct nl_mmap_hdr { | ||
133 | unsigned int nm_status; | ||
134 | unsigned int nm_len; | ||
135 | __u32 nm_group; | ||
136 | /* credentials */ | ||
137 | __u32 nm_pid; | ||
138 | __u32 nm_uid; | ||
139 | __u32 nm_gid; | ||
140 | }; | ||
141 | |||
142 | - nm_status is used for synchronizing processing between the kernel and user- | ||
143 | space and specifies ownership of the frame as well as the operation to perform | ||
144 | |||
145 | - nm_len contains the length of the message contained in the data area | ||
146 | |||
147 | - nm_group specified the destination multicast group of message | ||
148 | |||
149 | - nm_pid, nm_uid and nm_gid contain the netlink pid, UID and GID of the sending | ||
150 | process. These values correspond to the data available using SOCK_PASSCRED in | ||
151 | the SCM_CREDENTIALS cmsg. | ||
152 | |||
153 | The possible values in the status word are: | ||
154 | |||
155 | - NL_MMAP_STATUS_UNUSED: | ||
156 | RX ring: frame belongs to the kernel and contains no message | ||
157 | for user-space. Approriate action is to invoke poll() | ||
158 | to wait for new messages. | ||
159 | |||
160 | TX ring: frame belongs to user-space and can be used for | ||
161 | message construction. | ||
162 | |||
163 | - NL_MMAP_STATUS_RESERVED: | ||
164 | RX ring only: frame is currently used by the kernel for message | ||
165 | construction and contains no valid message yet. | ||
166 | Appropriate action is to invoke poll() to wait for | ||
167 | new messages. | ||
168 | |||
169 | - NL_MMAP_STATUS_VALID: | ||
170 | RX ring: frame contains a valid message. Approriate action is | ||
171 | to process the message and release the frame back to | ||
172 | the kernel by setting the status to | ||
173 | NL_MMAP_STATUS_UNUSED or queue the frame by setting the | ||
174 | status to NL_MMAP_STATUS_SKIP. | ||
175 | |||
176 | TX ring: the frame contains a valid message from user-space to | ||
177 | be processed by the kernel. After completing processing | ||
178 | the kernel will release the frame back to user-space by | ||
179 | setting the status to NL_MMAP_STATUS_UNUSED. | ||
180 | |||
181 | - NL_MMAP_STATUS_COPY: | ||
182 | RX ring only: a message is ready to be processed but could not be | ||
183 | stored in the ring, either because it exceeded the | ||
184 | frame size or because the originating subsystem does | ||
185 | not support memory mapped I/O. Appropriate action is | ||
186 | to invoke recvmsg() to receive the message and release | ||
187 | the frame back to the kernel by setting the status to | ||
188 | NL_MMAP_STATUS_UNUSED. | ||
189 | |||
190 | - NL_MMAP_STATUS_SKIP: | ||
191 | RX ring only: user-space queued the message for later processing, but | ||
192 | processed some messages following it in the ring. The | ||
193 | kernel should skip this frame when looking for unused | ||
194 | frames. | ||
195 | |||
196 | The data area of a frame begins at a offset of NL_MMAP_HDRLEN relative to the | ||
197 | frame header. | ||
198 | |||
199 | TX limitations | ||
200 | -------------- | ||
201 | |||
202 | Kernel processing usually involves validation of the message received by | ||
203 | user-space, then processing its contents. The kernel must assure that | ||
204 | userspace is not able to modify the message contents after they have been | ||
205 | validated. In order to do so, the message is copied from the ring frame | ||
206 | to an allocated buffer if either of these conditions is false: | ||
207 | |||
208 | - only a single mapping of the ring exists | ||
209 | - the file descriptor is not shared between processes | ||
210 | |||
211 | This means that for threaded programs, the kernel will fall back to copying. | ||
212 | |||
213 | Example | ||
214 | ------- | ||
215 | |||
216 | Ring setup: | ||
217 | |||
218 | unsigned int block_size = 16 * getpagesize(); | ||
219 | struct nl_mmap_req req = { | ||
220 | .nm_block_size = block_size, | ||
221 | .nm_block_nr = 64, | ||
222 | .nm_frame_size = 16384, | ||
223 | .nm_frame_nr = 64 * block_size / 16384, | ||
224 | }; | ||
225 | unsigned int ring_size; | ||
226 | void *rx_ring, *tx_ring; | ||
227 | |||
228 | /* Configure ring parameters */ | ||
229 | if (setsockopt(fd, NETLINK_RX_RING, &req, sizeof(req)) < 0) | ||
230 | exit(1); | ||
231 | if (setsockopt(fd, NETLINK_TX_RING, &req, sizeof(req)) < 0) | ||
232 | exit(1) | ||
233 | |||
234 | /* Calculate size of each invididual ring */ | ||
235 | ring_size = req.nm_block_nr * req.nm_block_size; | ||
236 | |||
237 | /* Map RX/TX rings. The TX ring is located after the RX ring */ | ||
238 | rx_ring = mmap(NULL, 2 * ring_size, PROT_READ | PROT_WRITE, | ||
239 | MAP_SHARED, fd, 0); | ||
240 | if ((long)rx_ring == -1L) | ||
241 | exit(1); | ||
242 | tx_ring = rx_ring + ring_size: | ||
243 | |||
244 | Message reception: | ||
245 | |||
246 | This example assumes some ring parameters of the ring setup are available. | ||
247 | |||
248 | unsigned int frame_offset = 0; | ||
249 | struct nl_mmap_hdr *hdr; | ||
250 | struct nlmsghdr *nlh; | ||
251 | unsigned char buf[16384]; | ||
252 | ssize_t len; | ||
253 | |||
254 | while (1) { | ||
255 | struct pollfd pfds[1]; | ||
256 | |||
257 | pfds[0].fd = fd; | ||
258 | pfds[0].events = POLLIN | POLLERR; | ||
259 | pfds[0].revents = 0; | ||
260 | |||
261 | if (poll(pfds, 1, -1) < 0 && errno != -EINTR) | ||
262 | exit(1); | ||
263 | |||
264 | /* Check for errors. Error handling omitted */ | ||
265 | if (pfds[0].revents & POLLERR) | ||
266 | <handle error> | ||
267 | |||
268 | /* If no new messages, poll again */ | ||
269 | if (!(pfds[0].revents & POLLIN)) | ||
270 | continue; | ||
271 | |||
272 | /* Process all frames */ | ||
273 | while (1) { | ||
274 | /* Get next frame header */ | ||
275 | hdr = rx_ring + frame_offset; | ||
276 | |||
277 | if (hdr->nm_status == NL_MMAP_STATUS_VALID) | ||
278 | /* Regular memory mapped frame */ | ||
279 | nlh = (void *hdr) + NL_MMAP_HDRLEN; | ||
280 | len = hdr->nm_len; | ||
281 | |||
282 | /* Release empty message immediately. May happen | ||
283 | * on error during message construction. | ||
284 | */ | ||
285 | if (len == 0) | ||
286 | goto release; | ||
287 | } else if (hdr->nm_status == NL_MMAP_STATUS_COPY) { | ||
288 | /* Frame queued to socket receive queue */ | ||
289 | len = recv(fd, buf, sizeof(buf), MSG_DONTWAIT); | ||
290 | if (len <= 0) | ||
291 | break; | ||
292 | nlh = buf; | ||
293 | } else | ||
294 | /* No more messages to process, continue polling */ | ||
295 | break; | ||
296 | |||
297 | process_msg(nlh); | ||
298 | release: | ||
299 | /* Release frame back to the kernel */ | ||
300 | hdr->nm_status = NL_MMAP_STATUS_UNUSED; | ||
301 | |||
302 | /* Advance frame offset to next frame */ | ||
303 | frame_offset = (frame_offset + frame_size) % ring_size; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | Message transmission: | ||
308 | |||
309 | This example assumes some ring parameters of the ring setup are available. | ||
310 | A single message is constructed and transmitted, to send multiple messages | ||
311 | at once they would be constructed in consecutive frames before a final call | ||
312 | to sendto(). | ||
313 | |||
314 | unsigned int frame_offset = 0; | ||
315 | struct nl_mmap_hdr *hdr; | ||
316 | struct nlmsghdr *nlh; | ||
317 | struct sockaddr_nl addr = { | ||
318 | .nl_family = AF_NETLINK, | ||
319 | }; | ||
320 | |||
321 | hdr = tx_ring + frame_offset; | ||
322 | if (hdr->nm_status != NL_MMAP_STATUS_UNUSED) | ||
323 | /* No frame available. Use poll() to avoid. */ | ||
324 | exit(1); | ||
325 | |||
326 | nlh = (void *)hdr + NL_MMAP_HDRLEN; | ||
327 | |||
328 | /* Build message */ | ||
329 | build_message(nlh); | ||
330 | |||
331 | /* Fill frame header: length and status need to be set */ | ||
332 | hdr->nm_len = nlh->nlmsg_len; | ||
333 | hdr->nm_status = NL_MMAP_STATUS_VALID; | ||
334 | |||
335 | if (sendto(fd, NULL, 0, 0, &addr, sizeof(addr)) < 0) | ||
336 | exit(1); | ||
337 | |||
338 | /* Advance frame offset to next frame */ | ||
339 | frame_offset = (frame_offset + frame_size) % ring_size; | ||
diff --git a/Documentation/networking/packet_mmap.txt b/Documentation/networking/packet_mmap.txt index 94444b152fbc..23dd80e82b8e 100644 --- a/Documentation/networking/packet_mmap.txt +++ b/Documentation/networking/packet_mmap.txt | |||
@@ -685,14 +685,342 @@ int main(int argc, char **argp) | |||
685 | } | 685 | } |
686 | 686 | ||
687 | ------------------------------------------------------------------------------- | 687 | ------------------------------------------------------------------------------- |
688 | + AF_PACKET TPACKET_V3 example | ||
689 | ------------------------------------------------------------------------------- | ||
690 | |||
691 | AF_PACKET's TPACKET_V3 ring buffer can be configured to use non-static frame | ||
692 | sizes by doing it's own memory management. It is based on blocks where polling | ||
693 | works on a per block basis instead of per ring as in TPACKET_V2 and predecessor. | ||
694 | |||
695 | It is said that TPACKET_V3 brings the following benefits: | ||
696 | *) ~15 - 20% reduction in CPU-usage | ||
697 | *) ~20% increase in packet capture rate | ||
698 | *) ~2x increase in packet density | ||
699 | *) Port aggregation analysis | ||
700 | *) Non static frame size to capture entire packet payload | ||
701 | |||
702 | So it seems to be a good candidate to be used with packet fanout. | ||
703 | |||
704 | Minimal example code by Daniel Borkmann based on Chetan Loke's lolpcap (compile | ||
705 | it with gcc -Wall -O2 blob.c, and try things like "./a.out eth0", etc.): | ||
706 | |||
707 | #include <stdio.h> | ||
708 | #include <stdlib.h> | ||
709 | #include <stdint.h> | ||
710 | #include <string.h> | ||
711 | #include <assert.h> | ||
712 | #include <net/if.h> | ||
713 | #include <arpa/inet.h> | ||
714 | #include <netdb.h> | ||
715 | #include <poll.h> | ||
716 | #include <unistd.h> | ||
717 | #include <signal.h> | ||
718 | #include <inttypes.h> | ||
719 | #include <sys/socket.h> | ||
720 | #include <sys/mman.h> | ||
721 | #include <linux/if_packet.h> | ||
722 | #include <linux/if_ether.h> | ||
723 | #include <linux/ip.h> | ||
724 | |||
725 | #define BLOCK_SIZE (1 << 22) | ||
726 | #define FRAME_SIZE 2048 | ||
727 | |||
728 | #define NUM_BLOCKS 64 | ||
729 | #define NUM_FRAMES ((BLOCK_SIZE * NUM_BLOCKS) / FRAME_SIZE) | ||
730 | |||
731 | #define BLOCK_RETIRE_TOV_IN_MS 64 | ||
732 | #define BLOCK_PRIV_AREA_SZ 13 | ||
733 | |||
734 | #define ALIGN_8(x) (((x) + 8 - 1) & ~(8 - 1)) | ||
735 | |||
736 | #define BLOCK_STATUS(x) ((x)->h1.block_status) | ||
737 | #define BLOCK_NUM_PKTS(x) ((x)->h1.num_pkts) | ||
738 | #define BLOCK_O2FP(x) ((x)->h1.offset_to_first_pkt) | ||
739 | #define BLOCK_LEN(x) ((x)->h1.blk_len) | ||
740 | #define BLOCK_SNUM(x) ((x)->h1.seq_num) | ||
741 | #define BLOCK_O2PRIV(x) ((x)->offset_to_priv) | ||
742 | #define BLOCK_PRIV(x) ((void *) ((uint8_t *) (x) + BLOCK_O2PRIV(x))) | ||
743 | #define BLOCK_HDR_LEN (ALIGN_8(sizeof(struct block_desc))) | ||
744 | #define BLOCK_PLUS_PRIV(sz_pri) (BLOCK_HDR_LEN + ALIGN_8((sz_pri))) | ||
745 | |||
746 | #ifndef likely | ||
747 | # define likely(x) __builtin_expect(!!(x), 1) | ||
748 | #endif | ||
749 | #ifndef unlikely | ||
750 | # define unlikely(x) __builtin_expect(!!(x), 0) | ||
751 | #endif | ||
752 | |||
753 | struct block_desc { | ||
754 | uint32_t version; | ||
755 | uint32_t offset_to_priv; | ||
756 | struct tpacket_hdr_v1 h1; | ||
757 | }; | ||
758 | |||
759 | struct ring { | ||
760 | struct iovec *rd; | ||
761 | uint8_t *map; | ||
762 | struct tpacket_req3 req; | ||
763 | }; | ||
764 | |||
765 | static unsigned long packets_total = 0, bytes_total = 0; | ||
766 | static sig_atomic_t sigint = 0; | ||
767 | |||
768 | void sighandler(int num) | ||
769 | { | ||
770 | sigint = 1; | ||
771 | } | ||
772 | |||
773 | static int setup_socket(struct ring *ring, char *netdev) | ||
774 | { | ||
775 | int err, i, fd, v = TPACKET_V3; | ||
776 | struct sockaddr_ll ll; | ||
777 | |||
778 | fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); | ||
779 | if (fd < 0) { | ||
780 | perror("socket"); | ||
781 | exit(1); | ||
782 | } | ||
783 | |||
784 | err = setsockopt(fd, SOL_PACKET, PACKET_VERSION, &v, sizeof(v)); | ||
785 | if (err < 0) { | ||
786 | perror("setsockopt"); | ||
787 | exit(1); | ||
788 | } | ||
789 | |||
790 | memset(&ring->req, 0, sizeof(ring->req)); | ||
791 | ring->req.tp_block_size = BLOCK_SIZE; | ||
792 | ring->req.tp_frame_size = FRAME_SIZE; | ||
793 | ring->req.tp_block_nr = NUM_BLOCKS; | ||
794 | ring->req.tp_frame_nr = NUM_FRAMES; | ||
795 | ring->req.tp_retire_blk_tov = BLOCK_RETIRE_TOV_IN_MS; | ||
796 | ring->req.tp_sizeof_priv = BLOCK_PRIV_AREA_SZ; | ||
797 | ring->req.tp_feature_req_word |= TP_FT_REQ_FILL_RXHASH; | ||
798 | |||
799 | err = setsockopt(fd, SOL_PACKET, PACKET_RX_RING, &ring->req, | ||
800 | sizeof(ring->req)); | ||
801 | if (err < 0) { | ||
802 | perror("setsockopt"); | ||
803 | exit(1); | ||
804 | } | ||
805 | |||
806 | ring->map = mmap(NULL, ring->req.tp_block_size * ring->req.tp_block_nr, | ||
807 | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, | ||
808 | fd, 0); | ||
809 | if (ring->map == MAP_FAILED) { | ||
810 | perror("mmap"); | ||
811 | exit(1); | ||
812 | } | ||
813 | |||
814 | ring->rd = malloc(ring->req.tp_block_nr * sizeof(*ring->rd)); | ||
815 | assert(ring->rd); | ||
816 | for (i = 0; i < ring->req.tp_block_nr; ++i) { | ||
817 | ring->rd[i].iov_base = ring->map + (i * ring->req.tp_block_size); | ||
818 | ring->rd[i].iov_len = ring->req.tp_block_size; | ||
819 | } | ||
820 | |||
821 | memset(&ll, 0, sizeof(ll)); | ||
822 | ll.sll_family = PF_PACKET; | ||
823 | ll.sll_protocol = htons(ETH_P_ALL); | ||
824 | ll.sll_ifindex = if_nametoindex(netdev); | ||
825 | ll.sll_hatype = 0; | ||
826 | ll.sll_pkttype = 0; | ||
827 | ll.sll_halen = 0; | ||
828 | |||
829 | err = bind(fd, (struct sockaddr *) &ll, sizeof(ll)); | ||
830 | if (err < 0) { | ||
831 | perror("bind"); | ||
832 | exit(1); | ||
833 | } | ||
834 | |||
835 | return fd; | ||
836 | } | ||
837 | |||
838 | #ifdef __checked | ||
839 | static uint64_t prev_block_seq_num = 0; | ||
840 | |||
841 | void assert_block_seq_num(struct block_desc *pbd) | ||
842 | { | ||
843 | if (unlikely(prev_block_seq_num + 1 != BLOCK_SNUM(pbd))) { | ||
844 | printf("prev_block_seq_num:%"PRIu64", expected seq:%"PRIu64" != " | ||
845 | "actual seq:%"PRIu64"\n", prev_block_seq_num, | ||
846 | prev_block_seq_num + 1, (uint64_t) BLOCK_SNUM(pbd)); | ||
847 | exit(1); | ||
848 | } | ||
849 | |||
850 | prev_block_seq_num = BLOCK_SNUM(pbd); | ||
851 | } | ||
852 | |||
853 | static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) | ||
854 | { | ||
855 | if (BLOCK_NUM_PKTS(pbd)) { | ||
856 | if (unlikely(bytes != BLOCK_LEN(pbd))) { | ||
857 | printf("block:%u with %upackets, expected len:%u != actual len:%u\n", | ||
858 | block_num, BLOCK_NUM_PKTS(pbd), bytes, BLOCK_LEN(pbd)); | ||
859 | exit(1); | ||
860 | } | ||
861 | } else { | ||
862 | if (unlikely(BLOCK_LEN(pbd) != BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ))) { | ||
863 | printf("block:%u, expected len:%lu != actual len:%u\n", | ||
864 | block_num, BLOCK_HDR_LEN, BLOCK_LEN(pbd)); | ||
865 | exit(1); | ||
866 | } | ||
867 | } | ||
868 | } | ||
869 | |||
870 | static void assert_block_header(struct block_desc *pbd, const int block_num) | ||
871 | { | ||
872 | uint32_t block_status = BLOCK_STATUS(pbd); | ||
873 | |||
874 | if (unlikely((block_status & TP_STATUS_USER) == 0)) { | ||
875 | printf("block:%u, not in TP_STATUS_USER\n", block_num); | ||
876 | exit(1); | ||
877 | } | ||
878 | |||
879 | assert_block_seq_num(pbd); | ||
880 | } | ||
881 | #else | ||
882 | static inline void assert_block_header(struct block_desc *pbd, const int block_num) | ||
883 | { | ||
884 | } | ||
885 | static void assert_block_len(struct block_desc *pbd, uint32_t bytes, int block_num) | ||
886 | { | ||
887 | } | ||
888 | #endif | ||
889 | |||
890 | static void display(struct tpacket3_hdr *ppd) | ||
891 | { | ||
892 | struct ethhdr *eth = (struct ethhdr *) ((uint8_t *) ppd + ppd->tp_mac); | ||
893 | struct iphdr *ip = (struct iphdr *) ((uint8_t *) eth + ETH_HLEN); | ||
894 | |||
895 | if (eth->h_proto == htons(ETH_P_IP)) { | ||
896 | struct sockaddr_in ss, sd; | ||
897 | char sbuff[NI_MAXHOST], dbuff[NI_MAXHOST]; | ||
898 | |||
899 | memset(&ss, 0, sizeof(ss)); | ||
900 | ss.sin_family = PF_INET; | ||
901 | ss.sin_addr.s_addr = ip->saddr; | ||
902 | getnameinfo((struct sockaddr *) &ss, sizeof(ss), | ||
903 | sbuff, sizeof(sbuff), NULL, 0, NI_NUMERICHOST); | ||
904 | |||
905 | memset(&sd, 0, sizeof(sd)); | ||
906 | sd.sin_family = PF_INET; | ||
907 | sd.sin_addr.s_addr = ip->daddr; | ||
908 | getnameinfo((struct sockaddr *) &sd, sizeof(sd), | ||
909 | dbuff, sizeof(dbuff), NULL, 0, NI_NUMERICHOST); | ||
910 | |||
911 | printf("%s -> %s, ", sbuff, dbuff); | ||
912 | } | ||
913 | |||
914 | printf("rxhash: 0x%x\n", ppd->hv1.tp_rxhash); | ||
915 | } | ||
916 | |||
917 | static void walk_block(struct block_desc *pbd, const int block_num) | ||
918 | { | ||
919 | int num_pkts = BLOCK_NUM_PKTS(pbd), i; | ||
920 | unsigned long bytes = 0; | ||
921 | unsigned long bytes_with_padding = BLOCK_PLUS_PRIV(BLOCK_PRIV_AREA_SZ); | ||
922 | struct tpacket3_hdr *ppd; | ||
923 | |||
924 | assert_block_header(pbd, block_num); | ||
925 | |||
926 | ppd = (struct tpacket3_hdr *) ((uint8_t *) pbd + BLOCK_O2FP(pbd)); | ||
927 | for (i = 0; i < num_pkts; ++i) { | ||
928 | bytes += ppd->tp_snaplen; | ||
929 | if (ppd->tp_next_offset) | ||
930 | bytes_with_padding += ppd->tp_next_offset; | ||
931 | else | ||
932 | bytes_with_padding += ALIGN_8(ppd->tp_snaplen + ppd->tp_mac); | ||
933 | |||
934 | display(ppd); | ||
935 | |||
936 | ppd = (struct tpacket3_hdr *) ((uint8_t *) ppd + ppd->tp_next_offset); | ||
937 | __sync_synchronize(); | ||
938 | } | ||
939 | |||
940 | assert_block_len(pbd, bytes_with_padding, block_num); | ||
941 | |||
942 | packets_total += num_pkts; | ||
943 | bytes_total += bytes; | ||
944 | } | ||
945 | |||
946 | void flush_block(struct block_desc *pbd) | ||
947 | { | ||
948 | BLOCK_STATUS(pbd) = TP_STATUS_KERNEL; | ||
949 | __sync_synchronize(); | ||
950 | } | ||
951 | |||
952 | static void teardown_socket(struct ring *ring, int fd) | ||
953 | { | ||
954 | munmap(ring->map, ring->req.tp_block_size * ring->req.tp_block_nr); | ||
955 | free(ring->rd); | ||
956 | close(fd); | ||
957 | } | ||
958 | |||
959 | int main(int argc, char **argp) | ||
960 | { | ||
961 | int fd, err; | ||
962 | socklen_t len; | ||
963 | struct ring ring; | ||
964 | struct pollfd pfd; | ||
965 | unsigned int block_num = 0; | ||
966 | struct block_desc *pbd; | ||
967 | struct tpacket_stats_v3 stats; | ||
968 | |||
969 | if (argc != 2) { | ||
970 | fprintf(stderr, "Usage: %s INTERFACE\n", argp[0]); | ||
971 | return EXIT_FAILURE; | ||
972 | } | ||
973 | |||
974 | signal(SIGINT, sighandler); | ||
975 | |||
976 | memset(&ring, 0, sizeof(ring)); | ||
977 | fd = setup_socket(&ring, argp[argc - 1]); | ||
978 | assert(fd > 0); | ||
979 | |||
980 | memset(&pfd, 0, sizeof(pfd)); | ||
981 | pfd.fd = fd; | ||
982 | pfd.events = POLLIN | POLLERR; | ||
983 | pfd.revents = 0; | ||
984 | |||
985 | while (likely(!sigint)) { | ||
986 | pbd = (struct block_desc *) ring.rd[block_num].iov_base; | ||
987 | retry_block: | ||
988 | if ((BLOCK_STATUS(pbd) & TP_STATUS_USER) == 0) { | ||
989 | poll(&pfd, 1, -1); | ||
990 | goto retry_block; | ||
991 | } | ||
992 | |||
993 | walk_block(pbd, block_num); | ||
994 | flush_block(pbd); | ||
995 | block_num = (block_num + 1) % NUM_BLOCKS; | ||
996 | } | ||
997 | |||
998 | len = sizeof(stats); | ||
999 | err = getsockopt(fd, SOL_PACKET, PACKET_STATISTICS, &stats, &len); | ||
1000 | if (err < 0) { | ||
1001 | perror("getsockopt"); | ||
1002 | exit(1); | ||
1003 | } | ||
1004 | |||
1005 | fflush(stdout); | ||
1006 | printf("\nReceived %u packets, %lu bytes, %u dropped, freeze_q_cnt: %u\n", | ||
1007 | stats.tp_packets, bytes_total, stats.tp_drops, | ||
1008 | stats.tp_freeze_q_cnt); | ||
1009 | |||
1010 | teardown_socket(&ring, fd); | ||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | ------------------------------------------------------------------------------- | ||
688 | + PACKET_TIMESTAMP | 1015 | + PACKET_TIMESTAMP |
689 | ------------------------------------------------------------------------------- | 1016 | ------------------------------------------------------------------------------- |
690 | 1017 | ||
691 | The PACKET_TIMESTAMP setting determines the source of the timestamp in | 1018 | The PACKET_TIMESTAMP setting determines the source of the timestamp in |
692 | the packet meta information. If your NIC is capable of timestamping | 1019 | the packet meta information for mmap(2)ed RX_RING and TX_RINGs. If your |
693 | packets in hardware, you can request those hardware timestamps to used. | 1020 | NIC is capable of timestamping packets in hardware, you can request those |
694 | Note: you may need to enable the generation of hardware timestamps with | 1021 | hardware timestamps to be used. Note: you may need to enable the generation |
695 | SIOCSHWTSTAMP. | 1022 | of hardware timestamps with SIOCSHWTSTAMP (see related information from |
1023 | Documentation/networking/timestamping.txt). | ||
696 | 1024 | ||
697 | PACKET_TIMESTAMP accepts the same integer bit field as | 1025 | PACKET_TIMESTAMP accepts the same integer bit field as |
698 | SO_TIMESTAMPING. However, only the SOF_TIMESTAMPING_SYS_HARDWARE | 1026 | SO_TIMESTAMPING. However, only the SOF_TIMESTAMPING_SYS_HARDWARE |
@@ -704,8 +1032,36 @@ SOF_TIMESTAMPING_RAW_HARDWARE if both bits are set. | |||
704 | req |= SOF_TIMESTAMPING_SYS_HARDWARE; | 1032 | req |= SOF_TIMESTAMPING_SYS_HARDWARE; |
705 | setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req)) | 1033 | setsockopt(fd, SOL_PACKET, PACKET_TIMESTAMP, (void *) &req, sizeof(req)) |
706 | 1034 | ||
707 | If PACKET_TIMESTAMP is not set, a software timestamp generated inside | 1035 | For the mmap(2)ed ring buffers, such timestamps are stored in the |
708 | the networking stack is used (the behavior before this setting was added). | 1036 | tpacket{,2,3}_hdr structure's tp_sec and tp_{n,u}sec members. To determine |
1037 | what kind of timestamp has been reported, the tp_status field is binary |'ed | ||
1038 | with the following possible bits ... | ||
1039 | |||
1040 | TP_STATUS_TS_SYS_HARDWARE | ||
1041 | TP_STATUS_TS_RAW_HARDWARE | ||
1042 | TP_STATUS_TS_SOFTWARE | ||
1043 | |||
1044 | ... that are equivalent to its SOF_TIMESTAMPING_* counterparts. For the | ||
1045 | RX_RING, if none of those 3 are set (i.e. PACKET_TIMESTAMP is not set), | ||
1046 | then this means that a software fallback was invoked *within* PF_PACKET's | ||
1047 | processing code (less precise). | ||
1048 | |||
1049 | Getting timestamps for the TX_RING works as follows: i) fill the ring frames, | ||
1050 | ii) call sendto() e.g. in blocking mode, iii) wait for status of relevant | ||
1051 | frames to be updated resp. the frame handed over to the application, iv) walk | ||
1052 | through the frames to pick up the individual hw/sw timestamps. | ||
1053 | |||
1054 | Only (!) if transmit timestamping is enabled, then these bits are combined | ||
1055 | with binary | with TP_STATUS_AVAILABLE, so you must check for that in your | ||
1056 | application (e.g. !(tp_status & (TP_STATUS_SEND_REQUEST | TP_STATUS_SENDING)) | ||
1057 | in a first step to see if the frame belongs to the application, and then | ||
1058 | one can extract the type of timestamp in a second step from tp_status)! | ||
1059 | |||
1060 | If you don't care about them, thus having it disabled, checking for | ||
1061 | TP_STATUS_AVAILABLE resp. TP_STATUS_WRONG_FORMAT is sufficient. If in the | ||
1062 | TX_RING part only TP_STATUS_AVAILABLE is set, then the tp_sec and tp_{n,u}sec | ||
1063 | members do not contain a valid value. For TX_RINGs, by default no timestamp | ||
1064 | is generated! | ||
709 | 1065 | ||
710 | See include/linux/net_tstamp.h and Documentation/networking/timestamping | 1066 | See include/linux/net_tstamp.h and Documentation/networking/timestamping |
711 | for more information on hardware timestamps. | 1067 | for more information on hardware timestamps. |
diff --git a/Documentation/networking/stmmac.txt b/Documentation/networking/stmmac.txt index f9fa6db40a52..654d2e55c8cb 100644 --- a/Documentation/networking/stmmac.txt +++ b/Documentation/networking/stmmac.txt | |||
@@ -1,6 +1,6 @@ | |||
1 | STMicroelectronics 10/100/1000 Synopsys Ethernet driver | 1 | STMicroelectronics 10/100/1000 Synopsys Ethernet driver |
2 | 2 | ||
3 | Copyright (C) 2007-2010 STMicroelectronics Ltd | 3 | Copyright (C) 2007-2013 STMicroelectronics Ltd |
4 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> | 4 | Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> |
5 | 5 | ||
6 | This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers | 6 | This is the driver for the MAC 10/100/1000 on-chip Ethernet controllers |
@@ -10,7 +10,7 @@ Currently this network device driver is for all STM embedded MAC/GMAC | |||
10 | (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 | 10 | (i.e. 7xxx/5xxx SoCs), SPEAr (arm), Loongson1B (mips) and XLINX XC2V3000 |
11 | FF1152AMT0221 D1215994A VIRTEX FPGA board. | 11 | FF1152AMT0221 D1215994A VIRTEX FPGA board. |
12 | 12 | ||
13 | DWC Ether MAC 10/100/1000 Universal version 3.60a (and older) and DWC Ether | 13 | DWC Ether MAC 10/100/1000 Universal version 3.70a (and older) and DWC Ether |
14 | MAC 10/100 Universal version 4.0 have been used for developing this driver. | 14 | MAC 10/100 Universal version 4.0 have been used for developing this driver. |
15 | 15 | ||
16 | This driver supports both the platform bus and PCI. | 16 | This driver supports both the platform bus and PCI. |
@@ -32,6 +32,8 @@ The kernel configuration option is STMMAC_ETH: | |||
32 | watchdog: transmit timeout (in milliseconds); | 32 | watchdog: transmit timeout (in milliseconds); |
33 | flow_ctrl: Flow control ability [on/off]; | 33 | flow_ctrl: Flow control ability [on/off]; |
34 | pause: Flow Control Pause Time; | 34 | pause: Flow Control Pause Time; |
35 | eee_timer: tx EEE timer; | ||
36 | chain_mode: select chain mode instead of ring. | ||
35 | 37 | ||
36 | 3) Command line options | 38 | 3) Command line options |
37 | Driver parameters can be also passed in command line by using: | 39 | Driver parameters can be also passed in command line by using: |
@@ -164,12 +166,12 @@ Where: | |||
164 | o bus_setup: perform HW setup of the bus. For example, on some ST platforms | 166 | o bus_setup: perform HW setup of the bus. For example, on some ST platforms |
165 | this field is used to configure the AMBA bridge to generate more | 167 | this field is used to configure the AMBA bridge to generate more |
166 | efficient STBus traffic. | 168 | efficient STBus traffic. |
167 | o init/exit: callbacks used for calling a custom initialisation; | 169 | o init/exit: callbacks used for calling a custom initialization; |
168 | this is sometime necessary on some platforms (e.g. ST boxes) | 170 | this is sometime necessary on some platforms (e.g. ST boxes) |
169 | where the HW needs to have set some PIO lines or system cfg | 171 | where the HW needs to have set some PIO lines or system cfg |
170 | registers. | 172 | registers. |
171 | o custom_cfg/custom_data: this is a custom configuration that can be passed | 173 | o custom_cfg/custom_data: this is a custom configuration that can be passed |
172 | while initialising the resources. | 174 | while initializing the resources. |
173 | o bsp_priv: another private poiter. | 175 | o bsp_priv: another private poiter. |
174 | 176 | ||
175 | For MDIO bus The we have: | 177 | For MDIO bus The we have: |
@@ -273,6 +275,8 @@ reset procedure etc). | |||
273 | o norm_desc.c: functions for handling normal descriptors; | 275 | o norm_desc.c: functions for handling normal descriptors; |
274 | o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes; | 276 | o chain_mode.c/ring_mode.c:: functions to manage RING/CHAINED modes; |
275 | o mmc_core.c/mmc.h: Management MAC Counters; | 277 | o mmc_core.c/mmc.h: Management MAC Counters; |
278 | o stmmac_hwtstamp.c: HW timestamp support for PTP | ||
279 | o stmmac_ptp.c: PTP 1588 clock | ||
276 | 280 | ||
277 | 5) Debug Information | 281 | 5) Debug Information |
278 | 282 | ||
@@ -326,6 +330,35 @@ To enter in Tx LPI mode the driver needs to have a software timer | |||
326 | that enable and disable the LPI mode when there is nothing to be | 330 | that enable and disable the LPI mode when there is nothing to be |
327 | transmitted. | 331 | transmitted. |
328 | 332 | ||
329 | 7) TODO: | 333 | 7) Extended descriptors |
334 | The extended descriptors give us information about the receive Ethernet payload | ||
335 | when it is carrying PTP packets or TCP/UDP/ICMP over IP. | ||
336 | These are not available on GMAC Synopsys chips older than the 3.50. | ||
337 | At probe time the driver will decide if these can be actually used. | ||
338 | This support also is mandatory for PTPv2 because the extra descriptors 6 and 7 | ||
339 | are used for saving the hardware timestamps. | ||
340 | |||
341 | 8) Precision Time Protocol (PTP) | ||
342 | The driver supports the IEEE 1588-2002, Precision Time Protocol (PTP), | ||
343 | which enables precise synchronization of clocks in measurement and | ||
344 | control systems implemented with technologies such as network | ||
345 | communication. | ||
346 | |||
347 | In addition to the basic timestamp features mentioned in IEEE 1588-2002 | ||
348 | Timestamps, new GMAC cores support the advanced timestamp features. | ||
349 | IEEE 1588-2008 that can be enabled when configure the Kernel. | ||
350 | |||
351 | 9) SGMII/RGMII supports | ||
352 | New GMAC devices provide own way to manage RGMII/SGMII. | ||
353 | This information is available at run-time by looking at the | ||
354 | HW capability register. This means that the stmmac can manage | ||
355 | auto-negotiation and link status w/o using the PHYLIB stuff | ||
356 | In fact, the HW provides a subset of extended registers to | ||
357 | restart the ANE, verify Full/Half duplex mode and Speed. | ||
358 | Also thanks to these registers it is possible to look at the | ||
359 | Auto-negotiated Link Parter Ability. | ||
360 | |||
361 | 10) TODO: | ||
330 | o XGMAC is not supported. | 362 | o XGMAC is not supported. |
331 | o Add the PTP - precision time protocol | 363 | o Complete the TBI & RTBI support. |
364 | o extened VLAN support for 3.70a SYNP GMAC. | ||