From 88dd921e24af0893734d4e197d646cfc7732ed54 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Thu, 7 Oct 2010 16:03:16 +0100 Subject: [PATCH] [netdevice] Pass both link-layer addresses in net_tx() and net_rx() FCoE requires the use of fabric-provided MAC addresses, which breaks the assumption that the net device's MAC address is implicitly the source address for net_tx() and the (unicast) destination address for net_rx(). Signed-off-by: Michael Brown --- src/include/ipxe/eapol.h | 5 +++-- src/include/ipxe/netdevice.h | 9 ++++++--- src/net/80211/wpa.c | 4 +++- src/net/aoe.c | 9 ++++++--- src/net/arp.c | 7 ++++--- src/net/eapol.c | 6 +++--- src/net/eth_slow.c | 7 +++++-- src/net/fcoe.c | 8 ++++---- src/net/ipv4.c | 8 ++++++-- src/net/ipv6.c | 5 ++++- src/net/netdevice.c | 15 ++++++++++----- src/net/rarp.c | 2 ++ src/usr/lotest.c | 6 ++++-- 13 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/include/ipxe/eapol.h b/src/include/ipxe/eapol.h index 43d891c6..3fad4428 100644 --- a/src/include/ipxe/eapol.h +++ b/src/include/ipxe/eapol.h @@ -90,7 +90,8 @@ struct eapol_handler * * @v iob I/O buffer containing packet payload * @v netdev Network device from which packet was received - * @v ll_source Source link-layer address from which packet was received + * @V ll_dest Destination link-layer address + * @v ll_source Source link-layer address * @ret rc Return status code * * The I/O buffer will have the EAPOL header pulled off it, so @@ -99,7 +100,7 @@ struct eapol_handler * This function takes ownership of the I/O buffer passed to it. */ int ( * rx ) ( struct io_buffer *iob, struct net_device *netdev, - const void *ll_source ); + const void *ll_dest, const void *ll_source ); }; #define EAPOL_HANDLERS __table ( struct eapol_handler, "eapol_handlers" ) diff --git a/src/include/ipxe/netdevice.h b/src/include/ipxe/netdevice.h index 80bc1c6e..8cec33ee 100644 --- a/src/include/ipxe/netdevice.h +++ b/src/include/ipxe/netdevice.h @@ -57,12 +57,13 @@ struct net_protocol { * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * * This method takes ownership of the I/O buffer. */ int ( * rx ) ( struct io_buffer *iobuf, struct net_device *netdev, - const void *ll_source ); + const void *ll_dest, const void *ll_source ); /** * Transcribe network-layer address * @@ -534,9 +535,11 @@ extern struct net_device * find_netdev_by_location ( unsigned int bus_type, unsigned int location ); extern struct net_device * last_opened_netdev ( void ); extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, - struct net_protocol *net_protocol, const void *ll_dest ); + struct net_protocol *net_protocol, const void *ll_dest, + const void *ll_source ); extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, - uint16_t net_proto, const void *ll_source ); + uint16_t net_proto, const void *ll_dest, + const void *ll_source ); /** * Complete network transmission diff --git a/src/net/80211/wpa.c b/src/net/80211/wpa.c index b676c63f..38ddb911 100644 --- a/src/net/80211/wpa.c +++ b/src/net/80211/wpa.c @@ -455,7 +455,7 @@ static int wpa_send_eapol ( struct io_buffer *iob, struct wpa_common_ctx *ctx, pkt->mic ); return net_tx ( iob, ctx->dev->netdev, &eapol_protocol, - ctx->dev->bssid ); + ctx->dev->bssid, ctx->dev->netdev->ll_addr ); } @@ -757,9 +757,11 @@ static int wpa_handle_1_of_2 ( struct wpa_common_ctx *ctx, * * @v iob I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Source link-layer address */ static int eapol_key_rx ( struct io_buffer *iob, struct net_device *netdev, + const void *ll_dest __unused, const void *ll_source ) { struct net80211_device *dev = net80211_get ( netdev ); diff --git a/src/net/aoe.c b/src/net/aoe.c index 8ee1f8bd..3b1953a2 100644 --- a/src/net/aoe.c +++ b/src/net/aoe.c @@ -249,13 +249,14 @@ static void aoecmd_close ( struct aoe_command *aoecmd, int rc ) { */ static int aoecmd_tx ( struct aoe_command *aoecmd ) { struct aoe_device *aoedev = aoecmd->aoedev; + struct net_device *netdev = aoedev->netdev; struct io_buffer *iobuf; struct aoehdr *aoehdr; size_t cmd_len; int rc; /* Sanity check */ - assert ( aoedev->netdev != NULL ); + assert ( netdev != NULL ); /* If we are transmitting anything that requires a response, * start the retransmission timer. Do this before attempting @@ -281,8 +282,8 @@ static int aoecmd_tx ( struct aoe_command *aoecmd ) { aoecmd->type->cmd ( aoecmd, iobuf->data, iob_len ( iobuf ) ); /* Send packet */ - if ( ( rc = net_tx ( iobuf, aoedev->netdev, &aoe_protocol, - aoedev->target ) ) != 0 ) { + if ( ( rc = net_tx ( iobuf, netdev, &aoe_protocol, aoedev->target, + netdev->ll_addr ) ) != 0 ) { DBGC ( aoedev, "AoE %s/%08x could not transmit: %s\n", aoedev_name ( aoedev ), aoecmd->tag, strerror ( rc ) ); @@ -903,12 +904,14 @@ static int aoedev_open ( struct interface *parent, struct net_device *netdev, * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * @ret rc Return status code * */ static int aoe_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused, + const void *ll_dest __unused, const void *ll_source ) { struct aoehdr *aoehdr = iobuf->data; struct aoe_command *aoecmd; diff --git a/src/net/arp.c b/src/net/arp.c index 714b471b..9b5fd220 100644 --- a/src/net/arp.c +++ b/src/net/arp.c @@ -155,8 +155,8 @@ int arp_resolve ( struct net_device *netdev, struct net_protocol *net_protocol, dest_net_addr, net_protocol->net_addr_len ); /* Transmit ARP request */ - if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol, - netdev->ll_broadcast ) ) != 0 ) + if ( ( rc = net_tx ( iobuf, netdev, &arp_protocol, + netdev->ll_broadcast, netdev->ll_addr ) ) != 0 ) return rc; return -ENOENT; @@ -195,6 +195,7 @@ static struct arp_net_protocol * arp_find_protocol ( uint16_t net_proto ) { * details. */ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev, + const void *ll_dest __unused, const void *ll_source __unused ) { struct arphdr *arphdr = iobuf->data; struct arp_net_protocol *arp_net_protocol; @@ -261,7 +262,7 @@ static int arp_rx ( struct io_buffer *iobuf, struct net_device *netdev, /* Send reply */ net_tx ( iob_disown ( iobuf ), netdev, &arp_protocol, - arp_target_ha ( arphdr ) ); + arp_target_ha ( arphdr ), netdev->ll_addr ); done: free_iob ( iobuf ); diff --git a/src/net/eapol.c b/src/net/eapol.c index 7246c7b8..9e5f2640 100644 --- a/src/net/eapol.c +++ b/src/net/eapol.c @@ -36,13 +36,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * @v iob I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * * This function takes ownership of the I/O buffer passed to it. */ static int eapol_rx ( struct io_buffer *iob, struct net_device *netdev, - const void *ll_source ) -{ + const void *ll_dest, const void *ll_source ) { struct eapol_frame *eapol = iob->data; struct eapol_handler *handler; @@ -54,7 +54,7 @@ static int eapol_rx ( struct io_buffer *iob, struct net_device *netdev, for_each_table_entry ( handler, EAPOL_HANDLERS ) { if ( handler->type == eapol->type ) { iob_pull ( iob, EAPOL_HDR_LEN ); - return handler->rx ( iob, netdev, ll_source ); + return handler->rx ( iob, netdev, ll_dest, ll_source ); } } diff --git a/src/net/eth_slow.c b/src/net/eth_slow.c index 4b2df280..e5c7ec9d 100644 --- a/src/net/eth_slow.c +++ b/src/net/eth_slow.c @@ -174,7 +174,8 @@ static int eth_slow_lacp_rx ( struct io_buffer *iobuf, /* Send response */ eth_slow_lacp_dump ( iobuf, netdev, "TX" ); - return net_tx ( iobuf, netdev, ð_slow_protocol, eth_slow_address ); + return net_tx ( iobuf, netdev, ð_slow_protocol, eth_slow_address, + netdev->ll_addr ); } /** @@ -218,7 +219,7 @@ static int eth_slow_marker_rx ( struct io_buffer *iobuf, marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE; eth_slow_marker_dump ( iobuf, netdev, "TX" ); return net_tx ( iobuf, netdev, ð_slow_protocol, - eth_slow_address ); + eth_slow_address, netdev->ll_addr ); } else { /* Discard all other marker packets */ free_iob ( iobuf ); @@ -231,11 +232,13 @@ static int eth_slow_marker_rx ( struct io_buffer *iobuf, * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * @ret rc Return status code */ static int eth_slow_rx ( struct io_buffer *iobuf, struct net_device *netdev, + const void *ll_dest __unused, const void *ll_source __unused ) { union eth_slow_packet *eth_slow = iobuf->data; diff --git a/src/net/fcoe.c b/src/net/fcoe.c index 87726044..11acfca2 100644 --- a/src/net/fcoe.c +++ b/src/net/fcoe.c @@ -129,7 +129,7 @@ static int fcoe_deliver ( struct fcoe_port *fcoe, /* Transmit packet */ if ( ( rc = net_tx ( iob_disown ( iobuf ), fcoe->netdev, &fcoe_protocol, - fcoe->fcf_ll_addr ) ) != 0 ) { + fcoe->fcf_ll_addr, fcoe->netdev->ll_addr )) != 0){ DBGC ( fcoe, "FCoE %s could not transmit: %s\n", fcoe->netdev->name, strerror ( rc ) ); goto done; @@ -164,12 +164,12 @@ static struct io_buffer * fcoe_alloc_iob ( struct fcoe_port *fcoe __unused, * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * @ret rc Return status code */ -static int fcoe_rx ( struct io_buffer *iobuf, - struct net_device *netdev, - const void *ll_source ) { +static int fcoe_rx ( struct io_buffer *iobuf, struct net_device *netdev, + const void *ll_dest __unused, const void *ll_source ) { struct fcoe_header *fcoehdr; struct fcoe_footer *fcoeftr; struct fcoe_port *fcoe; diff --git a/src/net/ipv4.c b/src/net/ipv4.c index 5918bbec..f6a1e6e0 100644 --- a/src/net/ipv4.c +++ b/src/net/ipv4.c @@ -355,7 +355,8 @@ static int ipv4_tx ( struct io_buffer *iobuf, ntohs ( iphdr->ident ), ntohs ( iphdr->chksum ) ); /* Hand off to link layer */ - if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest ) ) != 0 ) { + if ( ( rc = net_tx ( iobuf, netdev, &ipv4_protocol, ll_dest, + netdev->ll_addr ) ) != 0 ) { DBG ( "IPv4 could not transmit packet via %s: %s\n", netdev->name, strerror ( rc ) ); return rc; @@ -373,12 +374,15 @@ static int ipv4_tx ( struct io_buffer *iobuf, * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer destination source * * This function expects an IP4 network datagram. It processes the headers * and sends it to the transport layer. */ -static int ipv4_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused, +static int ipv4_rx ( struct io_buffer *iobuf, + struct net_device *netdev __unused, + const void *ll_dest __unused, const void *ll_source __unused ) { struct iphdr *iphdr = iobuf->data; size_t hdrlen; diff --git a/src/net/ipv6.c b/src/net/ipv6.c index ffaa558b..712aa49e 100644 --- a/src/net/ipv6.c +++ b/src/net/ipv6.c @@ -242,7 +242,8 @@ static int ipv6_tx ( struct io_buffer *iobuf, } /* Transmit packet */ - return net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest ); + return net_tx ( iobuf, netdev, &ipv6_protocol, ll_dest, + netdev->ll_addr ); err: free_iob ( iobuf ); @@ -285,12 +286,14 @@ static int ipv6_process_nxt_hdr ( struct io_buffer *iobuf, uint8_t nxt_hdr, * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * * This function processes a IPv6 packet */ static int ipv6_rx ( struct io_buffer *iobuf, __unused struct net_device *netdev, + __unused const void *ll_dest, __unused const void *ll_source ) { struct ip6_header *ip6hdr = iobuf->data; diff --git a/src/net/netdevice.c b/src/net/netdevice.c index bb8a5b28..894b7e79 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -607,6 +607,7 @@ struct net_device * last_opened_netdev ( void ) { * @v netdev Network device * @v net_protocol Network-layer protocol * @v ll_dest Destination link-layer address + * @v ll_source Source link-layer address * @ret rc Return status code * * Prepends link-layer headers to the I/O buffer and transmits the @@ -614,7 +615,8 @@ struct net_device * last_opened_netdev ( void ) { * ownership of the I/O buffer. */ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, - struct net_protocol *net_protocol, const void *ll_dest ) { + struct net_protocol *net_protocol, const void *ll_dest, + const void *ll_source ) { struct ll_protocol *ll_protocol = netdev->ll_protocol; int rc; @@ -626,7 +628,7 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, netdev_poll ( netdev ); /* Add link-layer header */ - if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, netdev->ll_addr, + if ( ( rc = ll_protocol->push ( netdev, iobuf, ll_dest, ll_source, net_protocol->net_proto ) ) != 0 ) { free_iob ( iobuf ); return rc; @@ -642,17 +644,19 @@ int net_tx ( struct io_buffer *iobuf, struct net_device *netdev, * @v iobuf I/O buffer * @v netdev Network device * @v net_proto Network-layer protocol, in network-byte order + * @v ll_dest Destination link-layer address * @v ll_source Source link-layer address * @ret rc Return status code */ int net_rx ( struct io_buffer *iobuf, struct net_device *netdev, - uint16_t net_proto, const void *ll_source ) { + uint16_t net_proto, const void *ll_dest, const void *ll_source ) { struct net_protocol *net_protocol; /* Hand off to network-layer protocol, if any */ for_each_table_entry ( net_protocol, NET_PROTOCOLS ) { if ( net_protocol->net_proto == net_proto ) - return net_protocol->rx ( iobuf, netdev, ll_source ); + return net_protocol->rx ( iobuf, netdev, ll_dest, + ll_source ); } DBGC ( netdev, "NETDEV %p unknown network protocol %04x\n", @@ -707,7 +711,8 @@ static void net_step ( struct process *process __unused ) { /* Hand packet to network layer */ if ( ( rc = net_rx ( iob_disown ( iobuf ), netdev, - net_proto, ll_source ) ) != 0 ) { + net_proto, ll_dest, + ll_source ) ) != 0 ) { /* Record error for diagnosis */ netdev_rx_err ( netdev, NULL, rc ); } diff --git a/src/net/rarp.c b/src/net/rarp.c index bf2e7f0a..da67c459 100644 --- a/src/net/rarp.c +++ b/src/net/rarp.c @@ -36,6 +36,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * @ret rc Return status code * @@ -43,6 +44,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); */ static int rarp_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused, + const void *ll_dest __unused, const void *ll_source __unused ) { free_iob ( iobuf ); return 0; diff --git a/src/usr/lotest.c b/src/usr/lotest.c index 8bbda51a..407f6844 100644 --- a/src/usr/lotest.c +++ b/src/usr/lotest.c @@ -45,11 +45,13 @@ FILE_LICENCE ( GPL2_OR_LATER ); * * @v iobuf I/O buffer * @v netdev Network device + * @v ll_dest Link-layer destination address * @v ll_source Link-layer source address * @ret rc Return status code */ static int lotest_rx ( struct io_buffer *iobuf, struct net_device *netdev __unused, + const void *ll_dest __unused, const void *ll_source __unused ) { free_iob ( iobuf ); return -ENOTSUP; @@ -138,8 +140,8 @@ int loopback_test ( struct net_device *sender, struct net_device *receiver, /* Transmit packet */ if ( ( rc = net_tx ( iob_disown ( iobuf ), sender, - &lotest_protocol, - receiver->ll_addr ) ) != 0 ) { + &lotest_protocol, receiver->ll_addr, + sender->ll_addr ) ) != 0 ) { printf ( "\nFailed to transmit packet: %s", strerror ( rc ) ); goto done;