Annotation of qemu/roms/ipxe/src/net/eth_slow.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2010 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23: #include <byteswap.h>
                     24: #include <errno.h>
                     25: #include <ipxe/iobuf.h>
                     26: #include <ipxe/netdevice.h>
                     27: #include <ipxe/if_ether.h>
                     28: #include <ipxe/ethernet.h>
                     29: #include <ipxe/eth_slow.h>
                     30: 
                     31: /** @file
                     32:  *
                     33:  * Ethernet slow protocols
                     34:  *
                     35:  * We implement a very simple passive LACP entity, that pretends that
                     36:  * each port is the only port on an individual system.  We avoid the
                     37:  * need for timeout logic (and retaining local state about our
                     38:  * partner) by requesting the same timeout period (1s or 30s) as our
                     39:  * partner requests, and then simply responding to every packet the
                     40:  * partner sends us.
                     41:  */
                     42: 
                     43: struct net_protocol eth_slow_protocol __net_protocol;
                     44: 
                     45: /** Slow protocols multicast address */
                     46: static const uint8_t eth_slow_address[ETH_ALEN] =
                     47:        { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x02 };
                     48: 
                     49: /**
                     50:  * Name LACP TLV type
                     51:  *
                     52:  * @v type             LACP TLV type
                     53:  * @ret name           Name of LACP TLV type
                     54:  */
                     55: static inline __attribute__ (( always_inline )) const char *
                     56: eth_slow_lacp_tlv_name ( uint8_t type ) {
                     57:        switch ( type ) {
                     58:        case ETH_SLOW_TLV_TERMINATOR:           return "terminator";
                     59:        case ETH_SLOW_TLV_LACP_ACTOR:           return "actor";
                     60:        case ETH_SLOW_TLV_LACP_PARTNER:         return "partner";
                     61:        case ETH_SLOW_TLV_LACP_COLLECTOR:       return "collector";
                     62:        default:                                return "<invalid>";
                     63:        }
                     64: }
                     65: 
                     66: /**
                     67:  * Name marker TLV type
                     68:  *
                     69:  * @v type             Marker TLV type
                     70:  * @ret name           Name of marker TLV type
                     71:  */
                     72: static inline __attribute__ (( always_inline )) const char *
                     73: eth_slow_marker_tlv_name ( uint8_t type ) {
                     74:        switch ( type ) {
                     75:        case ETH_SLOW_TLV_TERMINATOR:           return "terminator";
                     76:        case ETH_SLOW_TLV_MARKER_REQUEST:       return "request";
                     77:        case ETH_SLOW_TLV_MARKER_RESPONSE:      return "response";
                     78:        default:                                return "<invalid>";
                     79:        }
                     80: }
                     81: 
                     82: /**
                     83:  * Name LACP state
                     84:  *
                     85:  * @v state            LACP state
                     86:  * @ret name           LACP state name
                     87:  */
                     88: static const char * eth_slow_lacp_state_name ( uint8_t state ) {
                     89:        static char state_chars[] = "AFGSRTLX";
                     90:        unsigned int i;
                     91: 
                     92:        for ( i = 0 ; i < 8 ; i++ ) {
                     93:                state_chars[i] |= 0x20;
                     94:                if ( state & ( 1 << i ) )
                     95:                        state_chars[i] &= ~0x20;
                     96:        }
                     97:        return state_chars;
                     98: }
                     99: 
                    100: /**
                    101:  * Dump LACP packet
                    102:  *
                    103:  * @v iobuf            I/O buffer
                    104:  * @v netdev           Network device
                    105:  * @v label            "RX" or "TX"
                    106:  */
                    107: static void eth_slow_lacp_dump ( struct io_buffer *iobuf,
                    108:                                 struct net_device *netdev,
                    109:                                 const char *label ) {
                    110:        union eth_slow_packet *eth_slow = iobuf->data;
                    111:        struct eth_slow_lacp *lacp = &eth_slow->lacp;
                    112: 
                    113:        DBGC ( netdev,
                    114:               "SLOW %s %s LACP actor (%04x,%s,%04x,%02x,%04x) [%s]\n",
                    115:               netdev->name, label, ntohs ( lacp->actor.system_priority ),
                    116:               eth_ntoa ( lacp->actor.system ),
                    117:               ntohs ( lacp->actor.key ),
                    118:               ntohs ( lacp->actor.port_priority ),
                    119:               ntohs ( lacp->actor.port ),
                    120:               eth_slow_lacp_state_name ( lacp->actor.state ) );
                    121:        DBGC ( netdev,
                    122:               "SLOW %s %s LACP partner (%04x,%s,%04x,%02x,%04x) [%s]\n",
                    123:               netdev->name, label, ntohs ( lacp->partner.system_priority ),
                    124:               eth_ntoa ( lacp->partner.system ),
                    125:               ntohs ( lacp->partner.key ),
                    126:               ntohs ( lacp->partner.port_priority ),
                    127:               ntohs ( lacp->partner.port ),
                    128:               eth_slow_lacp_state_name ( lacp->partner.state ) );
                    129:        DBGC ( netdev, "SLOW %s %s LACP collector %04x (%d us)\n",
                    130:               netdev->name, label, ntohs ( lacp->collector.max_delay ),
                    131:               ( ntohs ( lacp->collector.max_delay ) * 10 ) );
                    132:        DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
                    133: }
                    134: 
                    135: /**
                    136:  * Process incoming LACP packet
                    137:  *
                    138:  * @v iobuf            I/O buffer
                    139:  * @v netdev           Network device
                    140:  * @ret rc             Return status code
                    141:  */
                    142: static int eth_slow_lacp_rx ( struct io_buffer *iobuf,
                    143:                              struct net_device *netdev ) {
                    144:        union eth_slow_packet *eth_slow = iobuf->data;
                    145:        struct eth_slow_lacp *lacp = &eth_slow->lacp;
                    146: 
                    147:        eth_slow_lacp_dump ( iobuf, netdev, "RX" );
                    148: 
                    149:        /* Build response */
                    150:        memset ( lacp->reserved, 0, sizeof ( lacp->reserved ) );
                    151:        memset ( &lacp->terminator, 0, sizeof ( lacp->terminator ) );
                    152:        memset ( &lacp->collector, 0, sizeof ( lacp->collector ) );
                    153:        lacp->collector.tlv.type = ETH_SLOW_TLV_LACP_COLLECTOR;
                    154:        lacp->collector.tlv.length = ETH_SLOW_TLV_LACP_COLLECTOR_LEN;
                    155:        memcpy ( &lacp->partner, &lacp->actor, sizeof ( lacp->partner ) );
                    156:        lacp->partner.tlv.type = ETH_SLOW_TLV_LACP_PARTNER;
                    157:        lacp->partner.tlv.length = ETH_SLOW_TLV_LACP_PARTNER_LEN;
                    158:        memset ( &lacp->partner.reserved, 0,
                    159:                 sizeof ( lacp->partner.reserved ) );
                    160:        memset ( &lacp->actor, 0, sizeof ( lacp->actor ) );
                    161:        lacp->actor.tlv.type = ETH_SLOW_TLV_LACP_ACTOR;
                    162:        lacp->actor.tlv.length = ETH_SLOW_TLV_LACP_ACTOR_LEN;
                    163:        lacp->actor.system_priority = htons ( LACP_SYSTEM_PRIORITY_MAX );
                    164:        memcpy ( lacp->actor.system, netdev->ll_addr,
                    165:                 sizeof ( lacp->actor.system ) );
                    166:        lacp->actor.key = htons ( 1 );
                    167:        lacp->actor.port_priority = htons ( LACP_PORT_PRIORITY_MAX );
                    168:        lacp->actor.port = htons ( 1 );
                    169:        lacp->actor.state = ( LACP_STATE_IN_SYNC |
                    170:                              LACP_STATE_COLLECTING |
                    171:                              LACP_STATE_DISTRIBUTING |
                    172:                              ( lacp->partner.state & LACP_STATE_FAST ) );
                    173:        lacp->header.version = ETH_SLOW_LACP_VERSION;
                    174: 
                    175:        /* Send response */
                    176:        eth_slow_lacp_dump ( iobuf, netdev, "TX" );
                    177:        return net_tx ( iobuf, netdev, &eth_slow_protocol, eth_slow_address,
                    178:                        netdev->ll_addr );
                    179: }
                    180: 
                    181: /**
                    182:  * Dump marker packet
                    183:  *
                    184:  * @v iobuf            I/O buffer
                    185:  * @v netdev           Network device
                    186:  * @v label            "RX" or "TX"
                    187:  */
                    188: static void eth_slow_marker_dump ( struct io_buffer *iobuf,
                    189:                                   struct net_device *netdev,
                    190:                                   const char *label ) {
                    191:        union eth_slow_packet *eth_slow = iobuf->data;
                    192:        struct eth_slow_marker *marker = &eth_slow->marker;
                    193: 
                    194:        DBGC ( netdev, "SLOW %s %s marker %s port %04x system %s xact %08x\n",
                    195:               netdev->name, label,
                    196:               eth_slow_marker_tlv_name ( marker->marker.tlv.type ),
                    197:               ntohs ( marker->marker.port ),
                    198:               eth_ntoa ( marker->marker.system ),
                    199:               ntohl ( marker->marker.xact ) );
                    200:        DBGC2_HDA ( netdev, 0, iobuf->data, iob_len ( iobuf ) );
                    201: }
                    202: 
                    203: /**
                    204:  * Process incoming marker packet
                    205:  *
                    206:  * @v iobuf            I/O buffer
                    207:  * @v netdev           Network device
                    208:  * @ret rc             Return status code
                    209:  */
                    210: static int eth_slow_marker_rx ( struct io_buffer *iobuf,
                    211:                                struct net_device *netdev ) {
                    212:        union eth_slow_packet *eth_slow = iobuf->data;
                    213:        struct eth_slow_marker *marker = &eth_slow->marker;
                    214: 
                    215:        eth_slow_marker_dump ( iobuf, netdev, "RX" );
                    216: 
                    217:        if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
                    218:                /* Send marker response */
                    219:                marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
                    220:                eth_slow_marker_dump ( iobuf, netdev, "TX" );
                    221:                return net_tx ( iobuf, netdev, &eth_slow_protocol,
                    222:                                eth_slow_address, netdev->ll_addr );
                    223:        } else {
                    224:                /* Discard all other marker packets */
                    225:                free_iob ( iobuf );
                    226:                return -EINVAL;
                    227:        }
                    228: }
                    229: 
                    230: /**
                    231:  * Process incoming slow packet
                    232:  *
                    233:  * @v iobuf            I/O buffer
                    234:  * @v netdev           Network device
                    235:  * @v ll_dest          Link-layer destination address
                    236:  * @v ll_source                Link-layer source address
                    237:  * @ret rc             Return status code
                    238:  */
                    239: static int eth_slow_rx ( struct io_buffer *iobuf,
                    240:                         struct net_device *netdev,
                    241:                         const void *ll_dest __unused,
                    242:                         const void *ll_source __unused ) {
                    243:        union eth_slow_packet *eth_slow = iobuf->data;
                    244: 
                    245:        /* Sanity checks */
                    246:        if ( iob_len ( iobuf ) < sizeof ( *eth_slow ) ) {
                    247:                free_iob ( iobuf );
                    248:                return -EINVAL;
                    249:        }
                    250: 
                    251:        /* Handle according to subtype */
                    252:        switch ( eth_slow->header.subtype ) {
                    253:        case ETH_SLOW_SUBTYPE_LACP:
                    254:                return eth_slow_lacp_rx ( iobuf, netdev );
                    255:        case ETH_SLOW_SUBTYPE_MARKER:
                    256:                return eth_slow_marker_rx ( iobuf, netdev );
                    257:        default:
                    258:                DBGC ( netdev, "SLOW %s RX unknown subtype %02x\n",
                    259:                       netdev->name, eth_slow->header.subtype );
                    260:                free_iob ( iobuf );
                    261:                return -EINVAL;
                    262:        }
                    263: }
                    264: 
                    265: /** Slow protocol */
                    266: struct net_protocol eth_slow_protocol __net_protocol = {
                    267:        .name = "Slow",
                    268:        .net_proto = htons ( ETH_P_SLOW ),
                    269:        .rx = eth_slow_rx,
                    270: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.