[netdevice] Add mechanism for reporting detailed link status codes
Expand the NETDEV_LINK_UP bit into a link_rc status code field,
allowing specific reasons for link failure to be reported via
"ifstat".
Originally-authored-by: Joshua Oreman <oremanj@rwcr.net>
[netdevice] Add netdev argument to link-layer push and pull handlers
In order to construct outgoing link-layer frames or parse incoming
ones properly, some protocols (such as 802.11) need more state than is
available in the existing variables passed to the link-layer protocol
handlers. To remedy this, add struct net_device *netdev as the first
argument to each of these functions, so that more information can be
fetched from the link layer-private part of the network device.
Updated all three call sites (netdevice.c, efi_snp.c, pxe_undi.c) and
both implementations (ethernet.c, ipoib.c) of ll_protocol to use the
new argument.
Signed-off-by: Michael Brown <mcb30@etherboot.org>
[tables] Redefine methods for accessing linker tables
Intel's C compiler (icc) chokes on the zero-length arrays that we
currently use as part of the mechanism for accessing linker table
entries. Abstract away the zero-length arrays, to make a port to icc
easier.
Introduce macros such as for_each_table_entry() to simplify the common
case of iterating over all entries in a linker table.
Represent table names as #defined string constants rather than
unquoted literals; this avoids visual confusion between table names
and C variable or type names, and also allows us to force a
compilation error in the event of incorrect table names.
[netdevice] Provide function to retrieve the most recently opened net device
There are currently four places within the codebase that use a
heuristic to guess the "boot network device", with varying degrees of
success. Add a feature to the net device core to maintain a list of
open network devices, in order of opening, and provide a function
last_opened_netdev() to retrieve the most recently opened net device.
This should do a better job than the current assortment of
guess_boot_netdev() functions.
[netdevice] Retain and report detailed error breakdowns
netdev_rx_err() and netdev_tx_complete_err() get passed the error
code, but currently use it only in debug messages.
Retain error numbers and frequencey counts for up to
NETDEV_MAX_UNIQUE_ERRORS (4) different errors for each of TX and RX.
This allows the "ifstat" command to report the reasons for TX/RX
errors in most cases, even in non-debug builds.
[settings] Add the notion of a "tag magic" to numbered settings
Settings can be constructed using a dotted-decimal notation, to allow
for access to unnamed settings. The default interpretation is as a
DHCP option number (with encapsulated options represented as
"<encapsulating option>.<encapsulated option>".
In several contexts (e.g. SMBIOS, Phantom CLP), it is useful to
interpret the dotted-decimal notation as referring to non-DHCP
options. In this case, it becomes necessary for these contexts to
ignore standard DHCP options, otherwise we end up trying to, for
example, retrieve the boot filename from SMBIOS.
Allow settings blocks to specify a "tag magic". When dotted-decimal
notation is used to construct a setting, the tag magic value of the
originating settings block will be ORed in to the tag number.
Store/fetch methods can then check for the magic number before
interpreting arbitrarily-numbered settings.
[netdevice] Change link-layer push() and pull() methods to take raw types
EFI requires us to be able to specify the source address for
individual transmitted packets, and to be able to extract the
destination address on received packets.
Take advantage of this to rationalise the push() and pull() methods so
that push() takes a (dest,source,proto) tuple and pull() returns a
(dest,source,proto) tuple.
[undi] Fill in ProtType correctly in PXENV_UNDI_ISR
Determine the network-layer packet type and fill it in for UNDI
clients. This is required by some NBPs such as emBoot's winBoot/i.
This change requires refactoring the link-layer portions of the
gPXE netdevice API, so that it becomes possible to strip the
link-layer header without passing the packet up the network stack.
Add a configuration settings block for each net device. This will
provide the parent scope for settings applicable only to that network
device (e.g. non-volatile options stored on the NIC, options obtained via
DHCP, etc.).
Expose the MAC address as a setting.
Use net_device_operations structure and netdev_nullify() to allow for
safe dropping of the netdev ref by the driver while other refs still
exist.
Add netdev_irq() method. Net device open()/close() methods should no
longer enable or disable IRQs.
Remove rx_quota; it wasn't used anywhere and added too much complexity
to implementing correct interrupt-masking behaviour in pxe_undi.c.
Add "name" field to struct device to allow human-readable hardware device
names.
Add "dev" pointer in struct net_device to tie network interfaces back to a
hardware device.
Force natural alignment of data types in __table() macros. This seems to
prevent gcc from taking the unilateral decision to occasionally increase
their alignment (which screws up the table packing).
We don't actually have a stdio.h header file. Our printf() functions are
defined in vsprintf.h. (This may change, since vsprintf.h is a
non-standard name, but for now it's the one to use.)
There should be no need to include vsprintf.h just for DBG() statements,
since include/compiler.h forces it in for a debug build anyway.
Clarified packet ownership transfer between a few functions.
Added a large number of missing calls to free_pkb(). In the case of UDP,
no received packets were ever freed, which lead to memory exhaustion
remarkably quickly once pxelinux started up.
In general, any function with _rx() in its name which accepts a pk_buff
*must* either call free_pkb() or pass the pkb to another _rx() function
(e.g. the next layer up the stack). Since the UDP (and TCP) layers don't
pass packet buffers up to the higher-layer protocols (the
"applications"), they must free the packet buffer after calling the
application's newdata() method.
Kill off the static single net device and move to proper dynamic
registration (which we need with the new device model).
Break the (flawed) assumption that all network-layer protocols can use
ARP; such network-layer protocols (i.e. IPv4) must now register as an ARP
protocol using ARP_NET_PROTOCOL() and provide a single method for checking
the existence of a local network-layer address.