mirror of
https://gitlab.com/qemu-project/ipxe.git
synced 2025-11-03 07:59:06 +08:00
Compare commits
9 Commits
loongarch6
...
pkgcache
| Author | SHA1 | Date | |
|---|---|---|---|
| fd484754e5 | |||
| ef0a6f4792 | |||
| c6901792f0 | |||
| a2bed43939 | |||
| 7cc305f7b4 | |||
| dc16de3204 | |||
| 6c0335adf6 | |||
| 8450fa4a7b | |||
| 4e456d9928 |
41
.github/workflows/build.yml
vendored
41
.github/workflows/build.yml
vendored
@ -4,14 +4,37 @@ on: push
|
||||
|
||||
jobs:
|
||||
|
||||
cache:
|
||||
name: Cache
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Cache packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache
|
||||
- name: Download packages
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y -d -o Acquire::Retries=50 \
|
||||
mtools syslinux isolinux \
|
||||
libc6-dev-i386 valgrind \
|
||||
gcc-arm-none-eabi gcc-aarch64-linux-gnu
|
||||
|
||||
x86:
|
||||
name: x86
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cached packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo dpkg --add-architecture i386
|
||||
@ -32,12 +55,18 @@ jobs:
|
||||
|
||||
arm32:
|
||||
name: ARM32
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cached packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt update
|
||||
@ -52,12 +81,18 @@ jobs:
|
||||
|
||||
arm64:
|
||||
name: ARM64
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
needs: cache
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Cached packages
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /var/cache/apt/archives/*.deb
|
||||
key: apt-cache
|
||||
- name: Install packages
|
||||
run: |
|
||||
sudo apt update
|
||||
|
||||
2
.github/workflows/coverity.yml
vendored
2
.github/workflows/coverity.yml
vendored
@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
submit:
|
||||
name: Submit
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#include <ipxe/arm_io.h>
|
||||
|
||||
#endif /* _BITS_IO_H */
|
||||
|
||||
@ -20,9 +20,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
/*
|
||||
* Physical<->Bus address mappings
|
||||
*
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
#define __asmcall
|
||||
#define __libgcc
|
||||
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
#define __asmcall
|
||||
#define __libgcc
|
||||
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
/** Declare a function with standard calling conventions */
|
||||
#define __asmcall __attribute__ (( cdecl, regparm(0) ))
|
||||
|
||||
|
||||
@ -9,6 +9,9 @@
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
#include <ipxe/x86_io.h>
|
||||
|
||||
#endif /* _BITS_IO_H */
|
||||
|
||||
@ -28,9 +28,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
*
|
||||
*/
|
||||
|
||||
/** Page shift */
|
||||
#define PAGE_SHIFT 12
|
||||
|
||||
/*
|
||||
* Physical<->Bus address mappings
|
||||
*
|
||||
|
||||
@ -8,6 +8,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
/** Unprefixed constant operand modifier */
|
||||
#define ASM_NO_PREFIX "c"
|
||||
|
||||
/** Declare a function with standard calling conventions */
|
||||
#define __asmcall __attribute__ (( regparm(0) ))
|
||||
|
||||
|
||||
@ -49,3 +49,6 @@ REQUIRE_OBJECT ( eth_slow );
|
||||
#ifdef NET_PROTO_EAPOL
|
||||
REQUIRE_OBJECT ( eapol );
|
||||
#endif
|
||||
#ifdef NET_PROTO_LLDP
|
||||
REQUIRE_OBJECT ( lldp );
|
||||
#endif
|
||||
|
||||
@ -26,6 +26,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define FDT_EFI
|
||||
|
||||
#define NET_PROTO_IPV6 /* IPv6 protocol */
|
||||
#define NET_PROTO_LLDP /* Link Layer Discovery protocol */
|
||||
|
||||
#define DOWNLOAD_PROTO_FILE /* Local filesystem access */
|
||||
|
||||
|
||||
@ -40,6 +40,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define NET_PROTO_STP /* Spanning Tree protocol */
|
||||
#define NET_PROTO_LACP /* Link Aggregation control protocol */
|
||||
#define NET_PROTO_EAPOL /* EAP over LAN protocol */
|
||||
//#define NET_PROTO_LLDP /* Link Layer Discovery protocol */
|
||||
|
||||
/*
|
||||
* PXE support
|
||||
|
||||
@ -205,6 +205,7 @@ int pci_read_config ( struct pci_device *pci ) {
|
||||
pci_read_config_dword ( pci, PCI_REVISION, &tmp );
|
||||
pci->class = ( tmp >> 8 );
|
||||
pci_read_config_byte ( pci, PCI_INTERRUPT_LINE, &pci->irq );
|
||||
pci_read_config_byte ( pci, PCI_HEADER_TYPE, &pci->hdrtype );
|
||||
pci_read_bases ( pci );
|
||||
|
||||
/* Initialise generic device component */
|
||||
|
||||
@ -262,10 +262,10 @@ static inline void eplatform_discard ( int dummy __unused, ... ) {}
|
||||
".balign 8\n\t" \
|
||||
"\n1:\n\t" \
|
||||
".long ( 4f - 1b )\n\t" \
|
||||
".long %c0\n\t" \
|
||||
".long %" ASM_NO_PREFIX "0\n\t" \
|
||||
".long ( 2f - 1b )\n\t" \
|
||||
".long ( 3f - 1b )\n\t" \
|
||||
".long %c1\n\t" \
|
||||
".long %" ASM_NO_PREFIX "1\n\t" \
|
||||
"\n2:\t.asciz \"" __einfo_desc ( einfo ) "\"\n\t" \
|
||||
"\n3:\t.asciz \"" __FILE__ "\"\n\t" \
|
||||
".balign 8\n\t" \
|
||||
|
||||
@ -295,6 +295,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define ERRFILE_ntp ( ERRFILE_NET | 0x00490000 )
|
||||
#define ERRFILE_httpntlm ( ERRFILE_NET | 0x004a0000 )
|
||||
#define ERRFILE_eap ( ERRFILE_NET | 0x004b0000 )
|
||||
#define ERRFILE_lldp ( ERRFILE_NET | 0x004c0000 )
|
||||
|
||||
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
|
||||
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )
|
||||
|
||||
@ -23,6 +23,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
#define ETH_P_SLOW 0x8809 /* Ethernet slow protocols */
|
||||
#define ETH_P_EAPOL 0x888E /* 802.1X EAP over LANs */
|
||||
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
|
||||
#define ETH_P_LLDP 0x88CC /* Link Layer Discovery Protocol */
|
||||
#define ETH_P_FCOE 0x8906 /* Fibre Channel over Ethernet */
|
||||
#define ETH_P_FIP 0x8914 /* FCoE Initialization Protocol */
|
||||
|
||||
|
||||
97
src/include/ipxe/lldp.h
Normal file
97
src/include/ipxe/lldp.h
Normal file
@ -0,0 +1,97 @@
|
||||
#ifndef _IPXE_LLDP_H
|
||||
#define _IPXE_LLDP_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Link Layer Discovery Protocol
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** An LLDP TLV header */
|
||||
struct lldp_tlv {
|
||||
/** Type and length */
|
||||
uint16_t type_len;
|
||||
/** Data */
|
||||
uint8_t data[0];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/**
|
||||
* Extract LLDP TLV type
|
||||
*
|
||||
* @v type_len Type and length
|
||||
* @ret type Type
|
||||
*/
|
||||
#define LLDP_TLV_TYPE( type_len ) ( (type_len) >> 9 )
|
||||
|
||||
/**
|
||||
* Extract LLDP TLV length
|
||||
*
|
||||
* @v type_len Type and length
|
||||
* @ret len Length
|
||||
*/
|
||||
#define LLDP_TLV_LEN( type_len ) ( (type_len) & 0x01ff )
|
||||
|
||||
/** End of LLDP data unit */
|
||||
#define LLDP_TYPE_END 0x00
|
||||
|
||||
/** LLDP settings block name */
|
||||
#define LLDP_SETTINGS_NAME "lldp"
|
||||
|
||||
/**
|
||||
* Construct LLDP setting tag
|
||||
*
|
||||
* LLDP settings are encoded as
|
||||
*
|
||||
* ${netX.lldp/<prefix>.<type>.<index>.<offset>.<length>}
|
||||
*
|
||||
* where
|
||||
*
|
||||
* <type> is the TLV type
|
||||
*
|
||||
* <offset> is the starting offset within the TLV value
|
||||
*
|
||||
* <length> is the length (or zero to read the from <offset> to the end)
|
||||
*
|
||||
* <prefix>, if it has a non-zero value, is the subtype byte string
|
||||
* of length <offset> to match at the start of the TLV value, up to
|
||||
* a maximum matched length of 4 bytes
|
||||
*
|
||||
* <index> is the index of the entry matching <type> and <prefix> to
|
||||
* be accessed, with zero indicating the first matching entry
|
||||
*
|
||||
* The <prefix> is designed to accommodate both matching of the OUI
|
||||
* within an organization-specific TLV (e.g. 0x0080c2 for IEEE 802.1
|
||||
* TLVs) and of a subtype byte as found within many TLVs.
|
||||
*
|
||||
* This encoding allows most LLDP values to be extracted easily. For
|
||||
* example
|
||||
*
|
||||
* System name: ${netX.lldp/5.0.0.0:string}
|
||||
*
|
||||
* System description: ${netX.lldp/6.0.0.0:string}
|
||||
*
|
||||
* Port description: ${netX.lldp/4.0.0.0:string}
|
||||
*
|
||||
* Port interface name: ${netX.lldp/5.2.0.1.0:string}
|
||||
*
|
||||
* Chassis MAC address: ${netX.lldp/4.1.0.1.0:hex}
|
||||
*
|
||||
* Management IPv4 address: ${netX.lldp/5.1.8.0.2.4:ipv4}
|
||||
*
|
||||
* Port VLAN ID: ${netX.lldp/0x0080c2.1.127.0.4.2:int16}
|
||||
*
|
||||
* Port VLAN name: ${netX.lldp/0x0080c2.3.127.0.7.0:string}
|
||||
*
|
||||
* Maximum frame size: ${netX.lldp/0x00120f.4.127.0.4.2:uint16}
|
||||
*
|
||||
*/
|
||||
#define LLDP_TAG( prefix, type, index, offset, length ) \
|
||||
( ( ( ( uint64_t ) (prefix) ) << 32 ) | \
|
||||
( (type) << 24 ) | ( (index) << 16 ) | \
|
||||
( (offset) << 8 ) | ( (length) << 0 ) )
|
||||
|
||||
#endif /* _IPXE_LLDP_H */
|
||||
76
src/include/ipxe/nonxen.h
Normal file
76
src/include/ipxe/nonxen.h
Normal file
@ -0,0 +1,76 @@
|
||||
#ifndef _IPXE_NONXEN_H
|
||||
#define _IPXE_NONXEN_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Stub Xen definitions for platforms with no Xen support
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
#define __XEN_GUEST_HANDLE(name) __guest_handle_ ## name
|
||||
|
||||
#define XEN_GUEST_HANDLE(name) __XEN_GUEST_HANDLE(name)
|
||||
|
||||
#define ___DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||
typedef type * __XEN_GUEST_HANDLE(name)
|
||||
|
||||
#define __DEFINE_XEN_GUEST_HANDLE(name, type) \
|
||||
___DEFINE_XEN_GUEST_HANDLE(name, type); \
|
||||
___DEFINE_XEN_GUEST_HANDLE(const_##name, const type)
|
||||
|
||||
#define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name)
|
||||
|
||||
typedef unsigned long xen_pfn_t;
|
||||
|
||||
typedef unsigned long xen_ulong_t;
|
||||
|
||||
struct arch_vcpu_info {};
|
||||
|
||||
struct arch_shared_info {};
|
||||
|
||||
#define XEN_LEGACY_MAX_VCPUS 0
|
||||
|
||||
struct xen_hypervisor;
|
||||
|
||||
static inline __attribute__ (( always_inline )) unsigned long
|
||||
xen_hypercall_1 ( struct xen_hypervisor *xen __unused,
|
||||
unsigned int hypercall __unused,
|
||||
unsigned long arg1 __unused ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) unsigned long
|
||||
xen_hypercall_2 ( struct xen_hypervisor *xen __unused,
|
||||
unsigned int hypercall __unused,
|
||||
unsigned long arg1 __unused, unsigned long arg2 __unused ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) unsigned long
|
||||
xen_hypercall_3 ( struct xen_hypervisor *xen __unused,
|
||||
unsigned int hypercall __unused,
|
||||
unsigned long arg1 __unused, unsigned long arg2 __unused,
|
||||
unsigned long arg3 __unused ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) unsigned long
|
||||
xen_hypercall_4 ( struct xen_hypervisor *xen __unused,
|
||||
unsigned int hypercall __unused,
|
||||
unsigned long arg1 __unused, unsigned long arg2 __unused,
|
||||
unsigned long arg3 __unused, unsigned long arg4 __unused ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline __attribute__ (( always_inline )) unsigned long
|
||||
xen_hypercall_5 ( struct xen_hypervisor *xen __unused,
|
||||
unsigned int hypercall __unused,
|
||||
unsigned long arg1 __unused, unsigned long arg2 __unused,
|
||||
unsigned long arg3 __unused, unsigned long arg4 __unused,
|
||||
unsigned long arg5 __unused ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* _IPXE_NONXEN_H */
|
||||
@ -227,6 +227,8 @@ struct pci_device {
|
||||
uint32_t class;
|
||||
/** Interrupt number */
|
||||
uint8_t irq;
|
||||
/** Header type */
|
||||
uint8_t hdrtype;
|
||||
/** Segment, bus, device, and function (bus:dev.fn) number */
|
||||
uint32_t busdevfn;
|
||||
/** Driver for this device */
|
||||
|
||||
@ -59,6 +59,10 @@ sub try_import_file {
|
||||
if ( /^\#include\s+[<\"](\S+)[>\"]/ ) {
|
||||
push @dependencies, catfile ( $subdir, $1 );
|
||||
}
|
||||
# Patch "Unsupported architecture" line
|
||||
if ( /^\#error\s+"Unsupported\sarchitecture"/ ) {
|
||||
$_ = "#include <bits/xen.h>"
|
||||
}
|
||||
# Write out line
|
||||
print $outfh "$_\n";
|
||||
# Apply FILE_LICENCE() immediately after include guard
|
||||
|
||||
@ -19,7 +19,7 @@ FILE_LICENCE ( MIT );
|
||||
#elif defined(__arm__) || defined (__aarch64__)
|
||||
#include "arch-arm.h"
|
||||
#else
|
||||
#error "Unsupported architecture"
|
||||
#include <bits/xen.h>
|
||||
#endif
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
@ -785,12 +785,22 @@ int efipci_info ( EFI_HANDLE device, struct efi_pci_device *efipci ) {
|
||||
*/
|
||||
static int efipci_supported ( EFI_HANDLE device ) {
|
||||
struct efi_pci_device efipci;
|
||||
uint8_t hdrtype;
|
||||
int rc;
|
||||
|
||||
/* Get PCI device information */
|
||||
if ( ( rc = efipci_info ( device, &efipci ) ) != 0 )
|
||||
return rc;
|
||||
|
||||
/* Do not attempt to drive bridges */
|
||||
hdrtype = efipci.pci.hdrtype;
|
||||
if ( ( hdrtype & PCI_HEADER_TYPE_MASK ) != PCI_HEADER_TYPE_NORMAL ) {
|
||||
DBGC ( device, "EFIPCI " PCI_FMT " type %02x is not type %02x\n",
|
||||
PCI_ARGS ( &efipci.pci ), hdrtype,
|
||||
PCI_HEADER_TYPE_NORMAL );
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
/* Look for a driver */
|
||||
if ( ( rc = pci_find_driver ( &efipci.pci ) ) != 0 ) {
|
||||
DBGC ( device, "EFIPCI " PCI_FMT " (%04x:%04x class %06x) "
|
||||
|
||||
340
src/net/lldp.c
Normal file
340
src/net/lldp.c
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
* You can also choose to distribute this program under the terms of
|
||||
* the Unmodified Binary Distribution Licence (as given in the file
|
||||
* COPYING.UBDL), provided that you have satisfied its requirements.
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Link Layer Discovery Protocol
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <byteswap.h>
|
||||
#include <ipxe/iobuf.h>
|
||||
#include <ipxe/netdevice.h>
|
||||
#include <ipxe/if_ether.h>
|
||||
#include <ipxe/settings.h>
|
||||
#include <ipxe/lldp.h>
|
||||
|
||||
/** An LLDP settings block */
|
||||
struct lldp_settings {
|
||||
/** Reference counter */
|
||||
struct refcnt refcnt;
|
||||
/** Settings interface */
|
||||
struct settings settings;
|
||||
/** List of LLDP settings blocks */
|
||||
struct list_head list;
|
||||
/** Name */
|
||||
const char *name;
|
||||
/** LLDP data */
|
||||
void *data;
|
||||
/** Length of LLDP data */
|
||||
size_t len;
|
||||
};
|
||||
|
||||
/** LLDP settings scope */
|
||||
static const struct settings_scope lldp_settings_scope;
|
||||
|
||||
/** List of LLDP settings blocks */
|
||||
static LIST_HEAD ( lldp_settings );
|
||||
|
||||
/**
|
||||
* Free LLDP settings block
|
||||
*
|
||||
* @v refcnt Reference counter
|
||||
*/
|
||||
static void lldp_free ( struct refcnt *refcnt ) {
|
||||
struct lldp_settings *lldpset =
|
||||
container_of ( refcnt, struct lldp_settings, refcnt );
|
||||
|
||||
DBGC ( lldpset, "LLDP %s freed\n", lldpset->name );
|
||||
list_del ( &lldpset->list );
|
||||
free ( lldpset->data );
|
||||
free ( lldpset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Find LLDP settings block
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret lldpset LLDP settings block
|
||||
*/
|
||||
static struct lldp_settings * lldp_find ( struct net_device *netdev ) {
|
||||
struct lldp_settings *lldpset;
|
||||
|
||||
/* Find matching LLDP settings block */
|
||||
list_for_each_entry ( lldpset, &lldp_settings, list ) {
|
||||
if ( netdev_settings ( netdev ) == lldpset->settings.parent )
|
||||
return lldpset;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check applicability of LLDP setting
|
||||
*
|
||||
* @v settings Settings block
|
||||
* @v setting Setting to fetch
|
||||
* @ret applies Setting applies within this settings block
|
||||
*/
|
||||
static int lldp_applies ( struct settings *settings __unused,
|
||||
const struct setting *setting ) {
|
||||
|
||||
return ( setting->scope == &lldp_settings_scope );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch value of LLDP setting
|
||||
*
|
||||
* @v settings Settings block
|
||||
* @v setting Setting to fetch
|
||||
* @v buf Buffer to fill with setting data
|
||||
* @v len Length of buffer
|
||||
* @ret len Length of setting data, or negative error
|
||||
*/
|
||||
static int lldp_fetch ( struct settings *settings,
|
||||
struct setting *setting,
|
||||
void *buf, size_t len ) {
|
||||
struct lldp_settings *lldpset =
|
||||
container_of ( settings, struct lldp_settings, settings );
|
||||
union {
|
||||
uint32_t high;
|
||||
uint8_t raw[4];
|
||||
} tag_prefix;
|
||||
uint32_t tag_low;
|
||||
uint8_t tag_type;
|
||||
uint8_t tag_index;
|
||||
uint8_t tag_offset;
|
||||
uint8_t tag_length;
|
||||
const void *match;
|
||||
const void *data;
|
||||
size_t match_len;
|
||||
size_t remaining;
|
||||
const struct lldp_tlv *tlv;
|
||||
unsigned int tlv_type_len;
|
||||
unsigned int tlv_type;
|
||||
unsigned int tlv_len;
|
||||
|
||||
/* Parse setting tag */
|
||||
tag_prefix.high = htonl ( setting->tag >> 32 );
|
||||
tag_low = setting->tag;
|
||||
tag_type = ( tag_low >> 24 );
|
||||
tag_index = ( tag_low >> 16 );
|
||||
tag_offset = ( tag_low >> 8 );
|
||||
tag_length = ( tag_low >> 0 );
|
||||
|
||||
/* Identify match prefix */
|
||||
match_len = tag_offset;
|
||||
if ( match_len > sizeof ( tag_prefix ) )
|
||||
match_len = sizeof ( tag_prefix );
|
||||
if ( ! tag_prefix.high )
|
||||
match_len = 0;
|
||||
match = &tag_prefix.raw[ sizeof ( tag_prefix ) - match_len ];
|
||||
|
||||
/* Locate matching TLV */
|
||||
for ( data = lldpset->data, remaining = lldpset->len ; remaining ;
|
||||
data += tlv_len, remaining -= tlv_len ) {
|
||||
|
||||
/* Parse TLV header */
|
||||
if ( remaining < sizeof ( *tlv ) ) {
|
||||
DBGC ( lldpset, "LLDP %s underlength TLV header\n",
|
||||
lldpset->name );
|
||||
DBGC_HDA ( lldpset, 0, data, remaining );
|
||||
break;
|
||||
}
|
||||
tlv = data;
|
||||
data += sizeof ( *tlv );
|
||||
remaining -= sizeof ( *tlv );
|
||||
tlv_type_len = ntohs ( tlv->type_len );
|
||||
tlv_type = LLDP_TLV_TYPE ( tlv_type_len );
|
||||
if ( tlv_type == LLDP_TYPE_END )
|
||||
break;
|
||||
tlv_len = LLDP_TLV_LEN ( tlv_type_len );
|
||||
if ( remaining < tlv_len ) {
|
||||
DBGC ( lldpset, "LLDP %s underlength TLV value\n",
|
||||
lldpset->name );
|
||||
DBGC_HDA ( lldpset, 0, data, remaining );
|
||||
break;
|
||||
}
|
||||
DBGC2 ( lldpset, "LLDP %s found type %d:\n",
|
||||
lldpset->name, tlv_type );
|
||||
DBGC2_HDA ( lldpset, 0, data, tlv_len );
|
||||
|
||||
/* Check for matching tag type */
|
||||
if ( tlv_type != tag_type )
|
||||
continue;
|
||||
|
||||
/* Check for matching prefix */
|
||||
if ( tlv_len < match_len )
|
||||
continue;
|
||||
if ( memcmp ( data, match, match_len ) != 0 )
|
||||
continue;
|
||||
|
||||
/* Check for matching index */
|
||||
if ( tag_index-- )
|
||||
continue;
|
||||
|
||||
/* Skip offset */
|
||||
if ( tlv_len < tag_offset )
|
||||
return 0;
|
||||
data += tag_offset;
|
||||
tlv_len -= tag_offset;
|
||||
|
||||
/* Set type if not already specified */
|
||||
if ( ! setting->type ) {
|
||||
setting->type = ( tag_length ? &setting_type_hex :
|
||||
&setting_type_string );
|
||||
}
|
||||
|
||||
/* Extract value */
|
||||
if ( tag_length && ( tlv_len > tag_length ) )
|
||||
tlv_len = tag_length;
|
||||
if ( len > tlv_len )
|
||||
len = tlv_len;
|
||||
memcpy ( buf, data, len );
|
||||
return tlv_len;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/** LLDP settings operations */
|
||||
static struct settings_operations lldp_settings_operations = {
|
||||
.applies = lldp_applies,
|
||||
.fetch = lldp_fetch,
|
||||
};
|
||||
|
||||
/**
|
||||
* Process LLDP packet
|
||||
*
|
||||
* @v iobuf I/O buffer
|
||||
* @v netdev Network device
|
||||
* @v ll_dest Link-layer destination address
|
||||
* @v ll_source Link-layer source address
|
||||
* @v flags Packet flags
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lldp_rx ( struct io_buffer *iobuf, struct net_device *netdev,
|
||||
const void *ll_dest, const void *ll_source,
|
||||
unsigned int flags __unused ) {
|
||||
struct lldp_settings *lldpset;
|
||||
size_t len;
|
||||
void *data;
|
||||
int rc;
|
||||
|
||||
/* Find matching LLDP settings block */
|
||||
lldpset = lldp_find ( netdev );
|
||||
if ( ! lldpset ) {
|
||||
DBGC ( netdev, "LLDP %s has no \"%s\" settings block\n",
|
||||
netdev->name, LLDP_SETTINGS_NAME );
|
||||
rc = -ENOENT;
|
||||
goto err_find;
|
||||
}
|
||||
|
||||
/* Create trimmed copy of received LLDP data */
|
||||
len = iob_len ( iobuf );
|
||||
data = malloc ( len );
|
||||
if ( ! data ) {
|
||||
rc = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
memcpy ( data, iobuf->data, len );
|
||||
|
||||
/* Free any existing LLDP data */
|
||||
free ( lldpset->data );
|
||||
|
||||
/* Transfer data to LLDP settings block */
|
||||
lldpset->data = data;
|
||||
lldpset->len = len;
|
||||
data = NULL;
|
||||
DBGC2 ( lldpset, "LLDP %s src %s ",
|
||||
lldpset->name, netdev->ll_protocol->ntoa ( ll_source ) );
|
||||
DBGC2 ( lldpset, "dst %s\n", netdev->ll_protocol->ntoa ( ll_dest ) );
|
||||
DBGC2_HDA ( lldpset, 0, lldpset->data, lldpset->len );
|
||||
|
||||
/* Success */
|
||||
rc = 0;
|
||||
|
||||
free ( data );
|
||||
err_alloc:
|
||||
err_find:
|
||||
free_iob ( iobuf );
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** LLDP protocol */
|
||||
struct net_protocol lldp_protocol __net_protocol = {
|
||||
.name = "LLDP",
|
||||
.net_proto = htons ( ETH_P_LLDP ),
|
||||
.rx = lldp_rx,
|
||||
};
|
||||
|
||||
/**
|
||||
* Create LLDP settings block
|
||||
*
|
||||
* @v netdev Network device
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
static int lldp_probe ( struct net_device *netdev ) {
|
||||
struct lldp_settings *lldpset;
|
||||
int rc;
|
||||
|
||||
/* Allocate LLDP settings block */
|
||||
lldpset = zalloc ( sizeof ( *lldpset ) );
|
||||
if ( ! lldpset ) {
|
||||
rc = -ENOMEM;
|
||||
goto err_alloc;
|
||||
}
|
||||
ref_init ( &lldpset->refcnt, lldp_free );
|
||||
settings_init ( &lldpset->settings, &lldp_settings_operations,
|
||||
&lldpset->refcnt, &lldp_settings_scope );
|
||||
list_add_tail ( &lldpset->list, &lldp_settings );
|
||||
lldpset->name = netdev->name;
|
||||
|
||||
/* Register settings */
|
||||
if ( ( rc = register_settings ( &lldpset->settings, netdev_settings ( netdev ),
|
||||
LLDP_SETTINGS_NAME ) ) != 0 ) {
|
||||
DBGC ( lldpset, "LLDP %s could not register settings: %s\n",
|
||||
lldpset->name, strerror ( rc ) );
|
||||
goto err_register;
|
||||
}
|
||||
DBGC ( lldpset, "LLDP %s registered\n", lldpset->name );
|
||||
|
||||
ref_put ( &lldpset->refcnt );
|
||||
return 0;
|
||||
|
||||
unregister_settings ( &lldpset->settings );
|
||||
err_register:
|
||||
ref_put ( &lldpset->refcnt );
|
||||
err_alloc:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** LLDP driver */
|
||||
struct net_driver lldp_driver __net_driver = {
|
||||
.name = "LLDP",
|
||||
.probe = lldp_probe,
|
||||
};
|
||||
@ -571,6 +571,10 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
||||
if ( peer->sin_port != htons ( BOOTPS_PORT ) )
|
||||
return;
|
||||
|
||||
/* Filter out non-selected servers */
|
||||
if ( server_id.s_addr != dhcp->server.s_addr )
|
||||
return;
|
||||
|
||||
/* Handle DHCPNAK */
|
||||
if ( msgtype == DHCPNAK ) {
|
||||
dhcp_defer ( dhcp );
|
||||
@ -580,8 +584,6 @@ static void dhcp_request_rx ( struct dhcp_session *dhcp,
|
||||
/* Filter out unacceptable responses */
|
||||
if ( msgtype /* BOOTP */ && ( msgtype != DHCPACK ) )
|
||||
return;
|
||||
if ( server_id.s_addr != dhcp->server.s_addr )
|
||||
return;
|
||||
if ( ip.s_addr != dhcp->offer.s_addr )
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user