Mercurial > archived > louis > epitech > mq > rathaxes
view e1000_implement_the_frame_transmission_chunk.patch @ 86:c99e69966dd3
WIP/Cleanup on the tranmission
author | Louis Opter <louis@lse.epitech.net> |
---|---|
date | Tue, 18 Sep 2012 08:57:14 +0200 |
parents | 5dda73e7d728 |
children | e9736ab70995 |
line wrap: on
line source
# HG changeset patch # Parent 42d6e2a573d077772c1a9c697cc066337569b129 rathaxes: start to queue up packets in the TX ring on the e1000 sample diff --git a/maintainers/CMakeScripts/Templates/MakefileLKM.in b/maintainers/CMakeScripts/Templates/MakefileLKM.in --- a/maintainers/CMakeScripts/Templates/MakefileLKM.in +++ b/maintainers/CMakeScripts/Templates/MakefileLKM.in @@ -1,6 +1,6 @@ # Disable this "coding-style" warning (seriously, you have to compile with # -pedantic to get it...) -EXTRA_CFLAGS = -Wno-declaration-after-statement +EXTRA_CFLAGS = -Wno-declaration-after-statement -std=gnu99 KDIR = /lib/modules/$(shell uname -r)/build obj-m := @LKM_OBJECTS@ diff --git a/rathaxes/samples/e1000/e1000.blt b/rathaxes/samples/e1000/e1000.blt --- a/rathaxes/samples/e1000/e1000.blt +++ b/rathaxes/samples/e1000/e1000.blt @@ -332,6 +332,30 @@ } } + template type e1000::TxFlags() + { + chunk LKM::includes() + { + static const ${e1000::TxFlags} force_enum_rtx_e1000_tx_flags_decl; + } + + chunk ::decl() + { + enum rtx_e1000_tx_flags + { + E1000_TX_FLAGS_CSUM = 0x00000001, + E1000_TX_FLAGS_VLAN = 0x00000002, + E1000_TX_FLAGS_TSO = 0x00000004, + E1000_TX_FLAGS_IPV4 = 0x00000008, + E1000_TX_FLAGS_NO_FCS = 0x00000010, + }; + } + + map + { + } + } + template sequence e1000::create_device() { chunk Ethernet::create_device(PCI::Device pdev, Ethernet::Device rtx_ether_ctx) @@ -964,4 +988,86 @@ } } } + + template sequence e1000::_xmit_tso_cksum_offload(Ethernet::Device ctx, Socket::SKBuff skb) + { + chunk ::CALL() + { + if (skb_is_gso(${skb}) || ${skb}->ip_summed == CHECKSUM_PARTIAL) + { + ${Log::info("xmit: the packet needs to be fragmented and/or checksummed but this not implemented yet!")}; + return NETDEV_TX_OK; + } + } + } + + template sequence e1000::_xmit_map_skbuff(Ethernet::Device ctx, Socket::SKBuff skb) + { + chunk ::CALL() + { + dma_addr_t buff_addr = dma_map_single( + &${ctx}->pci_dev->dev, + ${skb}->data, + skb_headlen(${skb}), + DMA_TO_DEVICE); + if (dma_mapping_error(&${ctx}->pci_dev->dev, buff_addr)) + { + ${Log::info("xmit: can't DMA map a SKBuff")}; + goto err_dma_map; + } + } + } + + template sequence e1000::_xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff skb) + { + chunk ::CALL() + { + } + } + + template sequence e1000::xmit(Ethernet::Device ctx, Socket::SKBuff skb) + { + chunk ::CALL() + { + typedef unsigned long int dma_addr_t; + + (void)1; // Issue 10 + /* + * Put packets on the TX ring, must return NETDEV_TX_OK or + * NETDEV_TX_BUSY. + */ + { + ${Log::info("xmit: skbuff details:")}; + ${skb.dump_infos()}; + } + + /* + * The transmission is going to be several steps: + * 1. TCP Segmentation Offload & Checksum Offloading: pick a + * descriptor from the tx ring and fill it as a contex + * descriptor to allow the card to slice into several packets + * according to the MSS; + * 2. DMA Map the skbuff data as slices of 4096; + * 3. Signal the hardware that data is available via a tx desc. + */ + + /* 1. Offloading */ + { // workaround #10 (and it's useful to workaround #47 too) + ${e1000::_xmit_tso_cksum_offload(ctx, skb)}; + } + + /* 2. Map the data */ + { + ${e1000::_xmit_map_skbuff(ctx, skb)}; + } + + /* 3. Update the TX Ring */ + { + ${e1000::_xmit_update_tx_ring(ctx, skb)}; + } + + err_dma_map: + return NETDEV_TX_OK; + } + } } diff --git a/rathaxes/samples/e1000/e1000.rti b/rathaxes/samples/e1000/e1000.rti --- a/rathaxes/samples/e1000/e1000.rti +++ b/rathaxes/samples/e1000/e1000.rti @@ -51,6 +51,12 @@ method decl(); } + provided type TxFlags + { + chunk LKM::includes(); + chunk ::decl(); + } + provided sequence create_device() { provided chunk Ethernet::create_device(PCI::Device, Ethernet::Device); @@ -109,6 +115,26 @@ provided chunk ::CALL(); } + provided sequence _xmit_tso_cksum_offload(Ethernet::Device, Socket::SKBuff) + { + provided chunk ::CALL(); + } + + provided sequence _xmit_map_skbuff(Ethernet::Device, Socket::SKBuff) + { + provided chunk ::CALL(); + } + + provided sequence _xmit_update_tx_ring(Ethernet::Device, Socket::SKBuff) + { + provided chunk ::CALL(); + } + + provided sequence xmit(Ethernet::Device, Socket::SKBuff) + { + provided chunk ::CALL(); + } + provided sequence register_read32(e1000::Context, e1000::Register) { provided chunk LKM::prototypes(); diff --git a/rathaxes/samples/e1000/ethernet.blt b/rathaxes/samples/e1000/ethernet.blt --- a/rathaxes/samples/e1000/ethernet.blt +++ b/rathaxes/samples/e1000/ethernet.blt @@ -1,6 +1,51 @@ with Ethernet, PCI, LKM, Log { - template type Ethernet::Net() + template type Ethernet::ProtocolId() + { + chunk LKM::prototypes() + { + static const char *rtx_ethernet_protocol_id_to_str(unsigned short); + } + + chunk LKM::data() + { + static const struct + { + const unsigned short id; + const char *name; + } rtx_ethernet_proto_table[] = + { + { ETH_P_IP, "IPv4" }, + { ETH_P_IPV6, "IPv6" }, + { ETH_P_ARP, "ARP" }, + }; + } + + chunk LKM::code() + { + static const char *rtx_ethernet_protocol_id_to_str(unsigned short proto_id) + { + for (int i = 0; + i != sizeof(rtx_ethernet_proto_table[0]) / sizeof(rtx_ethernet_proto_table); + i++) + if (proto_id == rtx_ethernet_proto_table[i].id) + return rtx_ethernet_proto_table[i].name; + + return "Unknown"; + } + } + + chunk to_str() + { + rtx_ethernet_protocol_id_to_str(${self}); + } + + map + { + } + } + + template type Ethernet::AbstractDevice() { chunk LKM::includes() { @@ -17,11 +62,6 @@ } } - /* - * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device - * from Linux. Ethernet::Device is the type that we use in the private - * field of the struct net_device. - */ template type Ethernet::Device() { chunk LKM::includes() @@ -52,7 +92,7 @@ } *rtx_ethernet_dev_p; } - chunk ::init(Ethernet::Net net_dev, PCI::Device pci_dev) + chunk ::init(Ethernet::AbstractDevice net_dev, PCI::Device pci_dev) { ${self} = netdev_priv(${net_dev}); /* @@ -100,11 +140,11 @@ { static int rtx_ethernet_xmit(struct sk_buff* skb, struct net_device *dev) { - ${cast local.dev as Ethernet::Device}; + struct rtx_ethernet_dev* rtx_ethernet_dev = netdev_priv(dev); + + ${cast local.rtx_ethernet_dev as Ethernet::Device}; ${cast local.skb as Socket::SKBuff}; - ${pointcut ::IMPLEMENTATION(local.dev, local.skb)}; - - return 0; + ${pointcut ::IMPLEMENTATION(local.rtx_ethernet_dev, local.skb)}; } } } diff --git a/rathaxes/samples/e1000/ethernet.rti b/rathaxes/samples/e1000/ethernet.rti --- a/rathaxes/samples/e1000/ethernet.rti +++ b/rathaxes/samples/e1000/ethernet.rti @@ -1,16 +1,33 @@ interface Ethernet : Socket, PCI, LKM { - provided type Net + provided type ProtocolId + { + chunk LKM::prototypes(); + chunk LKM::data(); + chunk LKM::code(); + method ::to_str(); + } + + /* + * This is the abstract type used by the Kernel to represent an ethernet + * device. + */ + provided type AbstractDevice { chunk LKM::includes(); method decl(); } + /* + * Unlike PCI::Device, Ethernet::Device doesn't match the struct net_device + * from Linux. Ethernet::Device is the type that we use in the private + * field of the struct net_device. + */ provided type Device { chunk LKM::includes(); method decl(); - method init(Ethernet::Net, PCI::Device); + method init(Ethernet::AbstractDevice, PCI::Device); } required variable ::string ifname; diff --git a/rathaxes/samples/e1000/lkm.rtx b/rathaxes/samples/e1000/lkm.rtx --- a/rathaxes/samples/e1000/lkm.rtx +++ b/rathaxes/samples/e1000/lkm.rtx @@ -46,6 +46,7 @@ Ethernet::send(Ethernet::Device dev, Socket::SKBuff skb) { Log::info("we have one packet to transmit!"); + e1000::xmit(dev, skb); } LKM::init() @@ -79,4 +80,10 @@ * 4096, 8192 and 16384 bytes: */ e1000::rx_buffer_len = 2048; + /* + * 4096 bytes maximum per transmit descriptor is used on Linux and FreeBSD, + * 2048 on Minix and HelenOS, I can't find why. If I understand the Intel + * man correctly, the maximum should be 16288 (see section 3.3.3). + */ + e1000::tx_max_data_per_desc = 4096; } diff --git a/rathaxes/samples/e1000/socket.blt b/rathaxes/samples/e1000/socket.blt --- a/rathaxes/samples/e1000/socket.blt +++ b/rathaxes/samples/e1000/socket.blt @@ -1,4 +1,4 @@ -with Socket, LKM +with Socket, LKM, Ethernet { template type Socket::SKBuff() { @@ -10,13 +10,41 @@ chunk ::decl() { - struct sk_buff; + typedef struct sk_buff *rtx_socket_skbuff_p; } chunk ::init() { } + chunk ::dump_infos() + { + /* + * We should use a Rathaxes log abstraction instead of pr_info here, + * but Rathaxes doesn't support functions with a variable number of + * arguments yet. + */ + unsigned short ethernet_proto = be16_to_cpu(${self}->protocol); + ${cast local.ethernet_proto as Ethernet::ProtocolId}; + + static const char * const ip_summed_values[] = { + "none", "unnecessary", "complete", "partial" + }; + + pr_info( + "\t protocol = %#-5x (%s)\n" + "\t len = %-5u data_len = %-5u head_len = %-5u\n" + "\t nr_frags = %u\n" + "\t gso_size = %-5u gso_segs = %-5u gso_type = %-5u\n" + "\tip_summed = %d (%s)", + ethernet_proto, "", // XXX: ${local.ethernet_proto.to_str()}, + ${self}->len, ${self}->data_len, skb_headlen(${self}), + skb_shinfo(${self})->nr_frags, + skb_shinfo(${self})->gso_size, skb_shinfo(${self})->gso_segs, skb_shinfo(${self})->gso_type, + ${self}->ip_summed, ip_summed_values[${self}->ip_summed] + ); + } + map { // some work may have to be done here in order diff --git a/rathaxes/samples/e1000/socket.rti b/rathaxes/samples/e1000/socket.rti --- a/rathaxes/samples/e1000/socket.rti +++ b/rathaxes/samples/e1000/socket.rti @@ -1,8 +1,10 @@ interface Socket : LKM { - provided type Socket::SKBuff { + provided type Socket::SKBuff + { chunk LKM::includes(); - method decl(); - method init(); + chunk ::decl(); + method ::init(); + method ::dump_infos(); } }