comparison e1000_implement_the_frame_transmission_chunk.patch @ 87:e9736ab70995

Add a couple of patches to the build system and WIP on the e1000 code architecture to implement the tranmission
author Louis Opter <louis@lse.epitech.net>
date Mon, 24 Sep 2012 09:13:15 +0200
parents c99e69966dd3
children 8ffcdd6aa410
comparison
equal deleted inserted replaced
86:c99e69966dd3 87:e9736ab70995
1 # HG changeset patch 1 # HG changeset patch
2 # Parent 42d6e2a573d077772c1a9c697cc066337569b129 2 # Parent 87ba2a19a59fb7be346ad40a57439b6b752b152e
3 rathaxes: start to queue up packets in the TX ring on the e1000 sample 3 rathaxes: start to queue up packets in the TX ring on the e1000 sample
4 4
5 diff --git a/maintainers/CMakeScripts/Templates/MakefileLKM.in b/maintainers/CMakeScripts/Templates/MakefileLKM.in 5 diff --git a/rathaxes/samples/e1000/CMakeLists.txt b/rathaxes/samples/e1000/CMakeLists.txt
6 --- a/maintainers/CMakeScripts/Templates/MakefileLKM.in 6 --- a/rathaxes/samples/e1000/CMakeLists.txt
7 +++ b/maintainers/CMakeScripts/Templates/MakefileLKM.in 7 +++ b/rathaxes/samples/e1000/CMakeLists.txt
8 @@ -1,6 +1,6 @@ 8 @@ -1,6 +1,22 @@
9 # Disable this "coding-style" warning (seriously, you have to compile with 9 -ADD_RATHAXES_SOURCES(e1000_src lkm.rtx
10 # -pedantic to get it...) 10 - RTI builtin.rti log.rti lkm.rti pci.rti socket.rti ethernet.rti e1000.rti
11 -EXTRA_CFLAGS = -Wno-declaration-after-statement 11 - BLT log.blt lkm.blt pci.blt socket.blt ethernet.blt e1000.blt)
12 +EXTRA_CFLAGS = -Wno-declaration-after-statement -std=gnu99 12 +ADD_RATHAXES_SOURCES(e1000_src
13 13 + lkm.rtx
14 KDIR = /lib/modules/$(shell uname -r)/build 14 + RTI
15 obj-m := @LKM_OBJECTS@ 15 + builtin.rti
16 + log.rti
17 + lkm.rti
18 + device.rti
19 + pci.rti
20 + socket.rti
21 + ethernet.rti
22 + e1000.rti
23 + BLT
24 + log.blt
25 + lkm.blt
26 + pci.blt
27 + device.blt
28 + socket.blt
29 + ethernet.blt
30 + e1000.blt)
31
32 IF (LINUX_KBUILD_DIR)
33 ADD_RATHAXES_LKM(e1000 e1000_src)
34 diff --git a/rathaxes/samples/e1000/device.blt b/rathaxes/samples/e1000/device.blt
35 new file mode 100644
36 --- /dev/null
37 +++ b/rathaxes/samples/e1000/device.blt
38 @@ -0,0 +1,25 @@
39 +with Device, LKM
40 +{
41 + template type Device::Device()
42 + {
43 + chunk LKM::includes()
44 + {
45 + #include <linux/device.h>
46 +
47 + static const ${Device::Device} force_rtx_device_decl;
48 + }
49 +
50 + chunk decl()
51 + {
52 + typedef struct device *rtx_device_p;
53 + }
54 +
55 + chunk init()
56 + {
57 + }
58 +
59 + map
60 + {
61 + }
62 + }
63 +}
64 diff --git a/rathaxes/samples/e1000/device.rti b/rathaxes/samples/e1000/device.rti
65 new file mode 100644
66 --- /dev/null
67 +++ b/rathaxes/samples/e1000/device.rti
68 @@ -0,0 +1,9 @@
69 +interface Device : LKM
70 +{
71 + provided type Device
72 + {
73 + chunk LKM::includes();
74 + method decl();
75 + method init();
76 + }
77 +}
16 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt 78 diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt
17 --- a/rathaxes/samples/e1000/e1000.blt 79 --- a/rathaxes/samples/e1000/e1000.blt
18 +++ b/rathaxes/samples/e1000/e1000.blt 80 +++ b/rathaxes/samples/e1000/e1000.blt
19 @@ -332,6 +332,30 @@ 81 @@ -110,9 +110,9 @@
82 {
83 unsigned int size;
84 struct rtx_e1000_rx_descriptor *base;
85 - void* /* dma_addr_t */ dma_base;
86 + dma_addr_t dma_base;
87 struct sk_buff *skbuffs[256 /* ${config.rx_ring_size} */];
88 - void* /* dma_addr_t */ dma_skbuffs[256 /* ${config.rx_ring_size} */];
89 + dma_addr_t dma_skbuffs[256 /* ${config.rx_ring_size} */];
90 };
91 }
92
93 @@ -148,11 +148,59 @@
94 struct rtx_e1000_tx_ring
95 {
96 unsigned int size;
97 + /* We should probably use ${e1000::TxDescriptor} here: */
98 struct rtx_e1000_tx_descriptor *base;
99 - void* /* dma_addr_t */ dma_base;
100 + dma_addr_t dma_base;
101 + /* indexes on base */
102 + unsigned int head;
103 + unsigned int tail;
104 };
105 }
106
107 + chunk LKM::prototypes()
108 + {
109 + static unsigned int rtx_e1000_tx_ring_descriptors_remaining(struct rtx_e1000_tx_ring *);
110 + static int rtx_e1000_tx_ring_tso_cksum_offload(struct rtx_e1000_tx_ring *, struct rtx_socket_skbuff *);
111 + static int rtx_e1000_tx_ring_put(struct rtx_e1000_tx_ring *, struct rtx_socket_skbuff *);
112 + }
113 +
114 + chunk LKM::code()
115 + {
116 + static unsigned int rtx_e1000_tx_ring_descriptors_remaining(struct rtx_e1000_tx_ring *self)
117 + {
118 + if (self->tail == self->head) /* ring is empty */
119 + return 256; /* XXX: ${config.tx_ring_size}; */
120 + if (self->tail > self->head)
121 + /* XXX: ${config.tx_ring_size} */
122 + return 256 - (self->tail - self->head);
123 + return self->head - self->tail;
124 + }
125 +
126 + static int rtx_e1000_tx_ring_tso_cksum_offload(struct rtx_e1000_tx_ring *self, struct rtx_socket_skbuff *skb)
127 + {
128 + return skb_is_gso(skb->skbuff) || skb->skbuff->ip_summed == CHECKSUM_PARTIAL;
129 + }
130 +
131 + static int rtx_e1000_tx_ring_put(struct rtx_e1000_tx_ring *self, struct rtx_socket_skbuff *skb)
132 + {
133 + return NETDEV_TX_OK;
134 + }
135 + }
136 +
137 + chunk descriptors_remaining()
138 + {
139 + rtx_e1000_tx_ring_descriptors_remaining(${self});
140 + }
141 +
142 + chunk tso_cksum_offload(Socket::SKBuff skb)
143 + {
144 + }
145 +
146 + chunk put(Socket::SKBuff skb)
147 + {
148 + rtx_e1000_tx_ring_put(${self}, &${skb});
149 + }
150 +
151 chunk ::init()
152 {
153 }
154 @@ -183,7 +231,7 @@
155 struct rtx_e1000_ctx
156 {
157 int bars;
158 - unsigned char /* __iomem */ *ioaddr;
159 + unsigned char __iomem *ioaddr;
160 int irq;
161
162 /* we can't use the Rathaxes type here (#8) */
163 @@ -334,6 +382,30 @@
20 } 164 }
21 } 165 }
22 166
23 + template type e1000::TxFlags() 167 + template type e1000::TxFlags()
24 + { 168 + {
45 + } 189 + }
46 + 190 +
47 template sequence e1000::create_device() 191 template sequence e1000::create_device()
48 { 192 {
49 chunk Ethernet::create_device(PCI::Device pdev, Ethernet::Device rtx_ether_ctx) 193 chunk Ethernet::create_device(PCI::Device pdev, Ethernet::Device rtx_ether_ctx)
50 @@ -964,4 +988,86 @@ 194 @@ -358,8 +430,8 @@
195 ${Log::info("e1000::create: pci_enable_device_mem failed")};
196 if (pci_request_selected_regions(${pdev}, ${rtx_ether_ctx}->hw_ctx.bars, ${config.name}))
197 ${Log::info("e1000::create: pci_request_selected_regions failed")};
198 - if (${config.set_master})
199 - pci_set_master(${pdev});
200 +// XXX if (${config.set_master})
201 +// XXX pci_set_master(${pdev});
202
203 /* 0 here is for BAR_0: */
204 ${rtx_ether_ctx}->hw_ctx.ioaddr = pci_ioremap_bar(${pdev}, 0);
205 @@ -630,8 +702,6 @@
206 {
207 chunk ::CALL()
208 {
209 - typedef unsigned long int dma_addr_t;
210 -
211 /*
212 * This part is documented in the Intel Gigabit Ethernet Controller
213 * Software Developper manual. (You can find it in the doc/hardware
214 @@ -733,7 +803,7 @@
215 hw_ctx->rx_ring.base = dma_alloc_coherent(
216 &${ctx}->pci_dev->dev,
217 hw_ctx->rx_ring.size,
218 - (dma_addr_t *)&hw_ctx->rx_ring.dma_base,
219 + &hw_ctx->rx_ring.dma_base,
220 GFP_KERNEL);
221 if (!hw_ctx->rx_ring.base)
222 {
223 @@ -758,7 +828,7 @@
224 ${Log::info("cannot allocate a skbuff for the rx ring")};
225 goto err_skbuffs_alloc;
226 }
227 - hw_ctx->rx_ring.dma_skbuffs[i] = (void *)dma_map_single(
228 + hw_ctx->rx_ring.dma_skbuffs[i] = dma_map_single(
229 &${ctx}->pci_dev->dev,
230 hw_ctx->rx_ring.skbuffs[i]->data,
231 ${config.rx_buffer_len},
232 @@ -820,7 +890,7 @@
233 hw_ctx->tx_ring.base = dma_alloc_coherent(
234 &${ctx}->pci_dev->dev,
235 hw_ctx->tx_ring.size,
236 - (dma_addr_t *)&hw_ctx->tx_ring.dma_base,
237 + &hw_ctx->tx_ring.dma_base,
238 GFP_KERNEL);
239 if (!hw_ctx->rx_ring.base)
240 {
241 @@ -838,6 +908,8 @@
242 /* 3. Setup TDH/TDT to zero: the queue is empty */
243 rtx_e1000_register_write32(hw_ctx, E1000_TDH, 0);
244 rtx_e1000_register_write32(hw_ctx, E1000_TDT, 0);
245 + hw_ctx->tx_ring.head = 0;
246 + hw_ctx->tx_ring.tail = 0;
247
248 /* 4. Set TCTL.PSP and enable the transmitter */
249 rtx_e1000_register_set32(hw_ctx, E1000_TCTL, E1000_TCTL_PSP|E1000_TCTL_PSP);
250 @@ -930,4 +1002,81 @@
51 } 251 }
52 } 252 }
53 } 253 }
54 + 254 +
55 + template sequence e1000::_xmit_tso_cksum_offload(Ethernet::Device ctx, Socket::SKBuff skb) 255 + template sequence e1000::_xmit_tso_cksum_offload(Ethernet::Device ctx, Socket::SKBuff skb)
56 + { 256 + {
57 + chunk ::CALL() 257 + chunk ::CALL()
58 + { 258 + {
59 + if (skb_is_gso(${skb}) || ${skb}->ip_summed == CHECKSUM_PARTIAL) 259 + }
60 + { 260 + }
61 + ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; 261 +
62 + return NETDEV_TX_OK; 262 + template sequence e1000::xmit(Ethernet::Device ctx, Socket::KernelSKBuff kernel_skb)
63 + }
64 + }
65 + }
66 +
67 + template sequence e1000::_xmit_map_skbuff(Ethernet::Device ctx, Socket::SKBuff skb)
68 + { 263 + {
69 + chunk ::CALL() 264 + chunk ::CALL()
70 + { 265 + {
71 + dma_addr_t buff_addr = dma_map_single(
72 + &${ctx}->pci_dev->dev,
73 + ${skb}->data,
74 + skb_headlen(${skb}),
75 + DMA_TO_DEVICE);
76 + if (dma_mapping_error(&${ctx}->pci_dev->dev, buff_addr))
77 + {
78 + ${Log::info("xmit: can't DMA map a SKBuff")};
79 + goto err_dma_map;
80 + }
81 + }
82 + }
83 +
84 + template sequence e1000::_xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff skb)
85 + {
86 + chunk ::CALL()
87 + {
88 + }
89 + }
90 +
91 + template sequence e1000::xmit(Ethernet::Device ctx, Socket::SKBuff skb)
92 + {
93 + chunk ::CALL()
94 + {
95 + typedef unsigned long int dma_addr_t;
96 +
97 + (void)1; // Issue 10
98 + /* 266 + /*
99 + * Put packets on the TX ring, must return NETDEV_TX_OK or 267 + * Put packets on the TX ring, must return NETDEV_TX_OK or
100 + * NETDEV_TX_BUSY. 268 + * NETDEV_TX_BUSY.
101 + */ 269 + */
102 + { 270 +
103 + ${Log::info("xmit: skbuff details:")}; 271 + /*
104 + ${skb.dump_infos()}; 272 + * XXX: This leaves a placeholder if I cast local.tx_ring as
105 + } 273 + * e1000::TxRing below.
274 + */
275 + ${Socket::SKBuff} skb;
276 + ${local.skb.init(kernel_skb)};
277 +
278 + /*
279 + * XXX: can't write ${e1000::TxRing} * (the placeholder isn't
280 + * resolved).
281 + */
282 + struct rtx_e1000_tx_ring *tx_ring = &${ctx}->hw_ctx.tx_ring;
283 + //${cast local.tx_ring as e1000::TxRing};
284 +
285 + ${Log::info("xmit: skbuff details:")};
286 + /*
287 + * skb is not expand on the bound C variable (should be rtx_skbuff),
288 + * which is funny because it works for the sequence template call
289 + * right after.
290 + */
291 + /*
292 + * XXX: doesn't work (I tried to pass self explicitely too):
293 + * ${local.skb.dump_infos()};
294 + */
295 + rtx_socket_skbuff_dump_infos(&skb);
106 + 296 +
107 + /* 297 + /*
108 + * The transmission is going to be several steps: 298 + * The transmission is going to be several steps:
109 + * 1. TCP Segmentation Offload & Checksum Offloading: pick a 299 + * 1. TCP Segmentation Offload & Checksum Offloading: pick a
110 + * descriptor from the tx ring and fill it as a contex 300 + * descriptor from the tx ring and fill it as a contex
112 + * according to the MSS; 302 + * according to the MSS;
113 + * 2. DMA Map the skbuff data as slices of 4096; 303 + * 2. DMA Map the skbuff data as slices of 4096;
114 + * 3. Signal the hardware that data is available via a tx desc. 304 + * 3. Signal the hardware that data is available via a tx desc.
115 + */ 305 + */
116 + 306 +
307 + /* XXX: same thing wanted to use: ${local.tx_ring.descriptors_remaining()} */
308 + if (!rtx_e1000_tx_ring_descriptors_remaining(tx_ring))
309 + return NETDEV_TX_BUSY;
310 +
117 + /* 1. Offloading */ 311 + /* 1. Offloading */
118 + { // workaround #10 (and it's useful to workaround #47 too) 312 + /* XXX: ${local.tx_ring.tso_cksum_offload(skb)}; */
119 + ${e1000::_xmit_tso_cksum_offload(ctx, skb)}; 313 + if (rtx_e1000_tx_ring_tso_cksum_offload(tx_ring, &skb))
314 + {
315 + ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")};
316 + return NETDEV_TX_OK;
120 + } 317 + }
121 + 318 +
122 + /* 2. Map the data */ 319 + /* 2. Map the data */
123 + { 320 + ${Device::Device} dev = &${ctx}->pci_dev->dev;
124 + ${e1000::_xmit_map_skbuff(ctx, skb)}; 321 + /* XXX: ${local.skb.dma_map(local.dev)}; */
125 + } 322 + rtx_socket_dma_map(&skb, dev);
126 + 323 +
127 + /* 3. Update the TX Ring */ 324 + /* 3. Update the TX Ring */
128 + { 325 + /* XXX: ${local.tx_ring.put(skb)}; */
129 + ${e1000::_xmit_update_tx_ring(ctx, skb)}; 326 + rtx_e1000_tx_ring_put(tx_ring, &skb);
130 + } 327 +
131 +
132 + err_dma_map:
133 + return NETDEV_TX_OK; 328 + return NETDEV_TX_OK;
134 + } 329 + }
135 + } 330 + }
136 } 331 }
137 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti 332 diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti
138 --- a/rathaxes/samples/e1000/e1000.rti 333 --- a/rathaxes/samples/e1000/e1000.rti
139 +++ b/rathaxes/samples/e1000/e1000.rti 334 +++ b/rathaxes/samples/e1000/e1000.rti
140 @@ -51,6 +51,12 @@ 335 @@ -31,8 +31,14 @@
336 provided type TxRing
337 {
338 chunk LKM::includes();
339 + chunk LKM::prototypes();
340 + chunk LKM::code();
341 method decl();
342 method init();
343 +
344 + method descriptors_remaining();
345 + method tso_cksum_offload(Socket::SKBuff);
346 + method put(Socket::SKBuff);
347 }
348
349 /*
350 @@ -51,6 +57,12 @@
141 method decl(); 351 method decl();
142 } 352 }
143 353
144 + provided type TxFlags 354 + provided type TxFlags
145 + { 355 + {
148 + } 358 + }
149 + 359 +
150 provided sequence create_device() 360 provided sequence create_device()
151 { 361 {
152 provided chunk Ethernet::create_device(PCI::Device, Ethernet::Device); 362 provided chunk Ethernet::create_device(PCI::Device, Ethernet::Device);
153 @@ -109,6 +115,26 @@ 363 @@ -109,6 +121,16 @@
154 provided chunk ::CALL(); 364 provided chunk ::CALL();
155 } 365 }
156 366
157 + provided sequence _xmit_tso_cksum_offload(Ethernet::Device, Socket::SKBuff) 367 + provided sequence _xmit_tso_cksum_offload(Ethernet::Device, Socket::SKBuff)
158 + { 368 + {
159 + provided chunk ::CALL(); 369 + provided chunk ::CALL();
160 + } 370 + }
161 + 371 +
162 + provided sequence _xmit_map_skbuff(Ethernet::Device, Socket::SKBuff) 372 + provided sequence xmit(Ethernet::Device, Socket::KernelSKBuff)
163 + {
164 + provided chunk ::CALL();
165 + }
166 +
167 + provided sequence _xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff)
168 + {
169 + provided chunk ::CALL();
170 + }
171 +
172 + provided sequence xmit(Ethernet::Device, Socket::SKBuff)
173 + { 373 + {
174 + provided chunk ::CALL(); 374 + provided chunk ::CALL();
175 + } 375 + }
176 + 376 +
177 provided sequence register_read32(e1000::Context, e1000::Register) 377 provided sequence register_read32(e1000::Context, e1000::Register)
178 { 378 {
179 provided chunk LKM::prototypes(); 379 provided chunk LKM::prototypes();
180 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt 380 diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt
181 --- a/rathaxes/samples/e1000/ethernet.blt 381 --- a/rathaxes/samples/e1000/ethernet.blt
182 +++ b/rathaxes/samples/e1000/ethernet.blt 382 +++ b/rathaxes/samples/e1000/ethernet.blt
183 @@ -1,6 +1,51 @@ 383 @@ -1,6 +1,56 @@
184 with Ethernet, PCI, LKM, Log 384 with Ethernet, PCI, LKM, Log
185 { 385 {
186 - template type Ethernet::Net() 386 - template type Ethernet::Net()
187 + template type Ethernet::ProtocolId() 387 + template type Ethernet::ProtocolId()
188 + { 388 + {
217 + 417 +
218 + return "Unknown"; 418 + return "Unknown";
219 + } 419 + }
220 + } 420 + }
221 + 421 +
422 + chunk decl()
423 + {
424 + typedef unsigned short rtx_ether_protocol_id;
425 + }
426 +
222 + chunk to_str() 427 + chunk to_str()
223 + { 428 + {
224 + rtx_ethernet_protocol_id_to_str(${self}); 429 + rtx_ethernet_protocol_id_to_str(${self});
225 + } 430 + }
226 + 431 +
231 + 436 +
232 + template type Ethernet::AbstractDevice() 437 + template type Ethernet::AbstractDevice()
233 { 438 {
234 chunk LKM::includes() 439 chunk LKM::includes()
235 { 440 {
236 @@ -17,11 +62,6 @@ 441 @@ -17,11 +67,6 @@
237 } 442 }
238 } 443 }
239 444
240 - /* 445 - /*
241 - * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device 446 - * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device
243 - * field of the struct net_device. 448 - * field of the struct net_device.
244 - */ 449 - */
245 template type Ethernet::Device() 450 template type Ethernet::Device()
246 { 451 {
247 chunk LKM::includes() 452 chunk LKM::includes()
248 @@ -52,7 +92,7 @@ 453 @@ -47,15 +92,15 @@
454 struct pci_dev *pci_dev;
455 struct net_device *net_dev;
456
457 - /* while waiting on issue #8 */
458 - //${e1000::Context} hw_ctx;
459 - // In the long-term, this may disappear for a new concept allowing
460 - // to embbed a descriptor defined and manipulated by the front-end
461 + /*
462 + * In the long-term, this may disappear for a new concept allowing
463 + * to embbed a descriptor defined and manipulated by the front-end
464 + */
465 ${pointcut Ethernet::SubContext()};
249 } *rtx_ethernet_dev_p; 466 } *rtx_ethernet_dev_p;
250 } 467 }
251 468
252 - chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev) 469 - chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev)
253 + chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev) 470 + chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev)
254 { 471 {
255 ${self} = netdev_priv(${net_dev}); 472 ${self} = netdev_priv(${net_dev});
256 /* 473 /*
257 @@ -100,11 +140,11 @@ 474 @@ -82,9 +127,8 @@
258 { 475 {
259 static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev) 476 static int rtx_ethernet_open(struct net_device *dev)
477 {
478 - struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
479 + ${Ethernet::Device} rtx_ether_dev = netdev_priv(dev);
480
481 - ${cast local.rtx_ether_dev as Ethernet::Device};
482 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
483
484 return 0;
485 @@ -92,7 +136,7 @@
486 }
487 }
488
489 - template sequence Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
490 + template sequence Ethernet::send(Ethernet::Device dev, Socket::KernelSKBuff skb)
491 {
492 chunk LKM::prototypes()
493 {
494 @@ -101,13 +145,11 @@
495
496 chunk LKM::code()
497 {
498 - static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev)
499 + static int rtx_ethernet_xmit(struct sk_buff* kernel_skb, struct net_device *net_dev)
260 { 500 {
261 - ${cast local.dev as Ethernet::Device}; 501 - ${cast local.dev as Ethernet::Device};
262 + struct rtx_ethernet_dev* rtx_ethernet_dev = netdev_priv(dev); 502 - ${cast local.skb as Socket::SKBuff};
263 +
264 + ${cast local.rtx_ethernet_dev as Ethernet::Device};
265 ${cast local.skb as Socket::SKBuff};
266 - ${pointcut ::IMPLEMENTATION(local.dev, local.skb)}; 503 - ${pointcut ::IMPLEMENTATION(local.dev, local.skb)};
267 - 504 -
268 - return 0; 505 - return 0;
269 + ${pointcut ::IMPLEMENTATION(local.rtx_ethernet_dev, local.skb)}; 506 + ${Ethernet::Device} rtx_ethernet_dev = netdev_priv(net_dev);
507 + ${cast local.kernel_skb as Socket::KernelSKBuff};
508 + ${pointcut ::IMPLEMENTATION(local.rtx_ethernet_dev, local.kernel_skb)};
270 } 509 }
271 } 510 }
272 } 511 }
512 @@ -123,9 +165,8 @@
513 {
514 static int rtx_ethernet_close(struct net_device *dev)
515 {
516 - struct rtx_ethernet_dev* rtx_ether_dev = netdev_priv(dev);
517 + ${Ethernet::Device} rtx_ether_dev = netdev_priv(dev);
518
519 - ${cast local.rtx_ether_dev as Ethernet::Device};
520 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
521
522 return 0;
523 @@ -148,11 +189,8 @@
524 {
525 static enum irqreturn rtx_ethernet_interrupt_handler(int irq, void *dev_id)
526 {
527 - struct rtx_ethernet_dev* rtx_ether_dev;
528 - struct rtx_e1000_ctx* ctx;
529 + ${Ethernet::Device} rtx_ether_dev = dev_id;
530
531 - rtx_ether_dev = dev_id;
532 - ${cast local.rtx_ether_dev as Ethernet::Device};
533 ${pointcut ::IMPLEMENTATION(local.rtx_ether_dev)};
534
535 return IRQ_NONE;
273 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti 536 diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti
274 --- a/rathaxes/samples/e1000/ethernet.rti 537 --- a/rathaxes/samples/e1000/ethernet.rti
275 +++ b/rathaxes/samples/e1000/ethernet.rti 538 +++ b/rathaxes/samples/e1000/ethernet.rti
276 @@ -1,16 +1,33 @@ 539 @@ -1,16 +1,30 @@
277 interface Ethernet : Socket, PCI, LKM 540 interface Ethernet : Socket, PCI, LKM
278 { 541 {
279 - provided type Net 542 - provided type Net
280 + provided type ProtocolId 543 + provided type ProtocolId
281 + { 544 + {
282 + chunk LKM::prototypes(); 545 + chunk LKM::prototypes();
283 + chunk LKM::data(); 546 + chunk LKM::data();
284 + chunk LKM::code(); 547 + chunk LKM::code();
285 + method ::to_str(); 548 + method decl();
286 + } 549 + method to_str();
287 + 550 + }
288 + /* 551 +
289 + * This is the abstract type used by the Kernel to represent an ethernet
290 + * device.
291 + */
292 + provided type AbstractDevice 552 + provided type AbstractDevice
293 { 553 {
294 chunk LKM::includes(); 554 chunk LKM::includes();
295 method decl(); 555 - method decl();
556 + method decl();
296 } 557 }
297 558
298 + /* 559 + /*
299 + * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device 560 + * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device
300 + * from Linux. Ethernet::Device is the type that we use in the private 561 + * from Linux. Ethernet::Device is the type that we use in the private
304 { 565 {
305 chunk LKM::includes(); 566 chunk LKM::includes();
306 method decl(); 567 method decl();
307 - method init(Ethernet::Net, PCI::Device); 568 - method init(Ethernet::Net, PCI::Device);
308 + method init(Ethernet::AbstractDevice, PCI::Device); 569 + method init(Ethernet::AbstractDevice, PCI::Device);
309 } 570 pointcut Ethernet::SubContext();
310 571 }
311 required variable ::string ifname; 572
573 @@ -22,7 +36,7 @@
574 provided chunk LKM::code();
575 }
576
577 - required sequence send(Ethernet::Device dev, Socket::SKBuff skb)
578 + required sequence send(Ethernet::Device, Socket::KernelSKBuff)
579 {
580 provided chunk LKM::prototypes();
581 provided chunk LKM::code();
312 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx 582 diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx
313 --- a/rathaxes/samples/e1000/lkm.rtx 583 --- a/rathaxes/samples/e1000/lkm.rtx
314 +++ b/rathaxes/samples/e1000/lkm.rtx 584 +++ b/rathaxes/samples/e1000/lkm.rtx
315 @@ -46,6 +46,7 @@ 585 @@ -1,4 +1,4 @@
316 Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) 586 -device LKM use LKM, PCI, Ethernet, Log
587 +device LKM use LKM, PCI, Ethernet, Log, Socket
588 {
589 Ethernet::open(Ethernet::Device dev)
590 {
591 @@ -43,9 +43,10 @@
592 e1000::handle_interrupt(dev);
593 }
594
595 - Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb)
596 + Ethernet::send(Ethernet::Device dev, Socket::KernelSKBuff skb)
317 { 597 {
318 Log::info("we have one packet to transmit!"); 598 Log::info("we have one packet to transmit!");
319 + e1000::xmit(dev, skb); 599 + e1000::xmit(dev, skb);
320 } 600 }
321 601
332 + e1000::tx_max_data_per_desc = 4096; 612 + e1000::tx_max_data_per_desc = 4096;
333 } 613 }
334 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt 614 diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt
335 --- a/rathaxes/samples/e1000/socket.blt 615 --- a/rathaxes/samples/e1000/socket.blt
336 +++ b/rathaxes/samples/e1000/socket.blt 616 +++ b/rathaxes/samples/e1000/socket.blt
337 @@ -1,4 +1,4 @@ 617 @@ -1,20 +1,104 @@
338 -with Socket, LKM 618 -with Socket, LKM
339 +with Socket, LKM, Ethernet 619 +with Socket, LKM, Device, Ethernet
340 { 620 {
621 + template type Socket::KernelSKBuff()
622 + {
623 + chunk LKM::includes()
624 + {
625 + #include <linux/skbuff.h>
626 +
627 + static const ${Socket::KernelSKBuff} force_rtx_socket_kernel_skbuff_decl;
628 + }
629 +
630 + chunk ::decl()
631 + {
632 + typedef struct sk_buff *rtx_socket_kernel_skbuff_p;
633 + }
634 +
635 + map
636 + {
637 + }
638 + }
639 +
341 template type Socket::SKBuff() 640 template type Socket::SKBuff()
342 { 641 {
343 @@ -10,13 +10,41 @@ 642 chunk LKM::includes()
643 {
644 - #include <linux/skbuff.h>
645 - static const ${Socket::SKBuff} force_rtx_lnux_skbuf_decl;
646 + static const ${Socket::SKBuff} force_rtx_socket_skbuff_decl;
647 }
344 648
345 chunk ::decl() 649 chunk ::decl()
346 { 650 {
347 - struct sk_buff; 651 - struct sk_buff;
348 + typedef struct sk_buff *rtx_socket_skbuff_p; 652 + struct rtx_socket_skbuff
349 } 653 + {
350 654 + struct sk_buff *skbuff;
351 chunk ::init() 655 + dma_addr_t dma_handle;
352 {
353 }
354
355 + chunk ::dump_infos()
356 + {
357 + /*
358 + * We should use a Rathaxes log abstraction instead of pr_info here,
359 + * but Rathaxes doesn't support functions with a variable number of
360 + * arguments yet.
361 + */
362 + unsigned short ethernet_proto = be16_to_cpu(${self}->protocol);
363 + ${cast local.ethernet_proto as Ethernet::ProtocolId};
364 +
365 + static const char * const ip_summed_values[] = {
366 + "none", "unnecessary", "complete", "partial"
367 + }; 656 + };
368 + 657 }
369 + pr_info( 658
370 + "\t protocol = %#-5x (%s)\n" 659 - chunk ::init()
371 + "\t len = %-5u data_len = %-5u head_len = %-5u\n" 660 + chunk LKM::prototypes()
372 + "\t nr_frags = %u\n" 661 {
373 + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u\n" 662 + static void rtx_socket_skbuff_dump_infos(struct rtx_socket_skbuff *);
374 + "\tip_summed = %d (%s)", 663 + static int rtx_socket_dma_map(struct rtx_socket_skbuff *, struct device *);
375 + ethernet_proto, "", // XXX: ${local.ethernet_proto.to_str()}, 664 + }
376 + ${self}->len, ${self}->data_len, skb_headlen(${self}), 665 +
377 + skb_shinfo(${self})->nr_frags, 666 + chunk LKM::code()
378 + skb_shinfo(${self})->gso_size, skb_shinfo(${self})->gso_segs, skb_shinfo(${self})->gso_type, 667 + {
379 + ${self}->ip_summed, ip_summed_values[${self}->ip_summed] 668 + static void rtx_socket_skbuff_dump_infos(struct rtx_socket_skbuff *self)
380 + ); 669 + {
381 + } 670 + /*
382 + 671 + * We should use a Rathaxes log abstraction instead of pr_info here,
672 + * but Rathaxes doesn't support functions with a variable number of
673 + * arguments yet.
674 + */
675 + ${Ethernet::ProtocolId} ethernet_proto = be16_to_cpu(self->skbuff->protocol);
676 + static const char * const ip_summed_values[] = {
677 + "none", "unnecessary", "complete", "partial"
678 + };
679 + struct skb_shared_info *shinfo = skb_shinfo(self->skbuff);
680 +
681 + pr_info(
682 + "\t protocol = %#-5x (%s)\n"
683 + "\t len = %-5u data_len = %-5u head_len = %-5u\n"
684 + "\t nr_frags = %u\n"
685 + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u\n"
686 + "\tip_summed = %d (%s)",
687 + ethernet_proto, rtx_ethernet_protocol_id_to_str(ethernet_proto) /* XXX: ${local.ethernet_proto.to_str()} */,
688 + self->skbuff->len, self->skbuff->data_len, skb_headlen(self->skbuff),
689 + shinfo->nr_frags, shinfo->gso_size, shinfo->gso_segs, shinfo->gso_type,
690 + self->skbuff->ip_summed, ip_summed_values[self->skbuff->ip_summed]
691 + );
692 + }
693 +
694 + static int rtx_socket_dma_map(struct rtx_socket_skbuff *self, struct device *dev)
695 + {
696 + self->dma_handle = dma_map_single(
697 + dev,
698 + self->skbuff->data,
699 + skb_headlen(self->skbuff),
700 + DMA_TO_DEVICE);
701 + return dma_mapping_error(dev, self->dma_handle);
702 + }
703 + }
704 +
705 + /*
706 + * XXX: the rathaxes argument kernel_skb is not actually bound to the
707 + * correct C variable from Ethernet::send() (so I named it as the C
708 + * variable I needed)
709 + */
710 + chunk ::init(Socket::KernelSKBuff kernel_skb)
711 + {
712 + ${self}.skbuff = kernel_skb;
713 + ${self}.dma_handle = 0;
714 + }
715 +
716 + chunk dump_infos()
717 + {
718 + rtx_socket_skbuff_dump_infos(${self});
719 + }
720 +
721 + chunk dma_map(Device::Device dev)
722 + {
723 + rtx_socket_dma_map(${self}, ${dev});
724 }
725
383 map 726 map
384 {
385 // some work may have to be done here in order
386 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti 727 diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti
387 --- a/rathaxes/samples/e1000/socket.rti 728 --- a/rathaxes/samples/e1000/socket.rti
388 +++ b/rathaxes/samples/e1000/socket.rti 729 +++ b/rathaxes/samples/e1000/socket.rti
389 @@ -1,8 +1,10 @@ 730 @@ -1,8 +1,19 @@
390 interface Socket : LKM 731 -interface Socket : LKM
732 +interface Socket : LKM, Device
391 { 733 {
392 - provided type Socket::SKBuff { 734 - provided type Socket::SKBuff {
393 + provided type Socket::SKBuff 735 - chunk LKM::includes();
394 + {
395 chunk LKM::includes();
396 - method decl(); 736 - method decl();
397 - method init(); 737 - method init();
398 + chunk ::decl(); 738 + provided type KernelSKBuff
399 + method ::init(); 739 + {
400 + method ::dump_infos(); 740 + chunk LKM::includes();
741 + method decl();
742 + }
743 +
744 + provided type SKBuff
745 + {
746 + chunk LKM::includes();
747 + chunk LKM::prototypes();
748 + chunk LKM::code();
749 + method decl();
750 + method init(Socket::KernelSKBuff);
751 + method dump_infos();
752 + method dma_map(Device::Device);
401 } 753 }
402 } 754 }