11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Spanning tree protocol; BPDU handling 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Linux ethernet bridge 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors: 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Lennert Buytenhek <buytenh@gnu.org> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2 of the License, or (at your option) any later version. 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netfilter_bridge.h> 16cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger#include <linux/etherdevice.h> 17cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger#include <linux/llc.h> 185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 19547b4e718115eea74087e28d7fa70aec619200dbStephen Hemminger#include <linux/pkt_sched.h> 20e730c15519d09ea528b4d2f1103681fa5937c0e6Eric W. Biederman#include <net/net_namespace.h> 2112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger#include <net/llc.h> 22cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger#include <net/llc_pdu.h> 237c85fbf0657f216557b0c9c4a2e4e07f37d8bb8cPatrick McHardy#include <net/stp.h> 244dc6d9cc38cea1004a7f827cf76409ae42231feePeter Chubb#include <asm/unaligned.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "br_private.h" 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "br_private_stp.h" 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2918fdb2b25be37e49b1669b5c394671f8c5b6550fStephen Hemminger#define STP_HZ 256 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger#define LLC_RESERVE sizeof(struct llc_pdu_un) 3212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 3312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemmingerstatic void br_send_bpdu(struct net_bridge_port *p, 349d6f229fc45b6ac268020c0c8eff29e94bb34381YOSHIFUJI Hideaki const unsigned char *data, int length) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sk_buff *skb; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger skb = dev_alloc_skb(length+LLC_RESERVE); 3912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger if (!skb) 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger skb->dev = p->dev; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds skb->protocol = htons(ETH_P_802_2); 44547b4e718115eea74087e28d7fa70aec619200dbStephen Hemminger skb->priority = TC_PRIO_CONTROL; 4512ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 4612ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger skb_reserve(skb, LLC_RESERVE); 4712ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger memcpy(__skb_put(skb, length), data, length); 4812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 4912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger llc_pdu_header_init(skb, LLC_PDU_TYPE_U, LLC_SAP_BSPAN, 5012ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger LLC_SAP_BSPAN, LLC_PDU_CMD); 5112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger llc_pdu_init_as_ui_cmd(skb); 5212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 5312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 55e6f26129ebbb0071016e2526036f42036ccf30e1Florian Westphal skb_reset_mac_header(skb); 56e6f26129ebbb0071016e2526036f42036ccf30e1Florian Westphal 57713aefa3fb3929ce36305d4d1b7b4059d87ed115Jan Engelhardt NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev_queue_xmit); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6118fdb2b25be37e49b1669b5c394671f8c5b6550fStephen Hemmingerstatic inline void br_set_ticks(unsigned char *dest, int j) 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6318fdb2b25be37e49b1669b5c394671f8c5b6550fStephen Hemminger unsigned long ticks = (STP_HZ * j)/ HZ; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 65d3e2ce3bcdbf4319dea308c79b5f72a8ecc8015cHarvey Harrison put_unaligned_be16(ticks, dest); 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6818fdb2b25be37e49b1669b5c394671f8c5b6550fStephen Hemmingerstatic inline int br_get_ticks(const unsigned char *src) 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 70d3e2ce3bcdbf4319dea308c79b5f72a8ecc8015cHarvey Harrison unsigned long ticks = get_unaligned_be16(src); 7118fdb2b25be37e49b1669b5c394671f8c5b6550fStephen Hemminger 72172589ccdde41b59861c92c4a971b95514ef24e3Ilpo Järvinen return DIV_ROUND_UP(ticks * HZ, STP_HZ); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* called under bridge lock */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid br_send_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu) 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger unsigned char buf[35]; 7912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 809cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger if (p->br->stp_enabled != BR_KERNEL_STP) 819cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger return; 829cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger 8312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[0] = 0; 8412ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[1] = 0; 8512ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[2] = 0; 8612ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[3] = BPDU_TYPE_CONFIG; 8712ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[4] = (bpdu->topology_change ? 0x01 : 0) | 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (bpdu->topology_change_ack ? 0x80 : 0); 8912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[5] = bpdu->root.prio[0]; 9012ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[6] = bpdu->root.prio[1]; 9112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[7] = bpdu->root.addr[0]; 9212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[8] = bpdu->root.addr[1]; 9312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[9] = bpdu->root.addr[2]; 9412ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[10] = bpdu->root.addr[3]; 9512ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[11] = bpdu->root.addr[4]; 9612ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[12] = bpdu->root.addr[5]; 9712ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[13] = (bpdu->root_path_cost >> 24) & 0xFF; 9812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[14] = (bpdu->root_path_cost >> 16) & 0xFF; 9912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[15] = (bpdu->root_path_cost >> 8) & 0xFF; 10012ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[16] = bpdu->root_path_cost & 0xFF; 10112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[17] = bpdu->bridge_id.prio[0]; 10212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[18] = bpdu->bridge_id.prio[1]; 10312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[19] = bpdu->bridge_id.addr[0]; 10412ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[20] = bpdu->bridge_id.addr[1]; 10512ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[21] = bpdu->bridge_id.addr[2]; 10612ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[22] = bpdu->bridge_id.addr[3]; 10712ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[23] = bpdu->bridge_id.addr[4]; 10812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[24] = bpdu->bridge_id.addr[5]; 10912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[25] = (bpdu->port_id >> 8) & 0xFF; 11012ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[26] = bpdu->port_id & 0xFF; 11112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 11212ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger br_set_ticks(buf+27, bpdu->message_age); 11312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger br_set_ticks(buf+29, bpdu->max_age); 11412ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger br_set_ticks(buf+31, bpdu->hello_time); 11512ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger br_set_ticks(buf+33, bpdu->forward_delay); 11612ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 11712ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger br_send_bpdu(p, buf, 35); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* called under bridge lock */ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid br_send_tcn_bpdu(struct net_bridge_port *p) 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 12312ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger unsigned char buf[4]; 12412ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger 1259cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger if (p->br->stp_enabled != BR_KERNEL_STP) 1269cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger return; 1279cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger 12812ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[0] = 0; 12912ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[1] = 0; 13012ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[2] = 0; 13112ac84c4a9c505e3e30529563b04cc8f6d5ebbf3Stephen Hemminger buf[3] = BPDU_TYPE_TCN; 132485c2967d622449f4bbfae305a6fc4e185b5b094Stephen Hemminger br_send_bpdu(p, buf, 4); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 135cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger/* 136cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger * Called from llc. 137cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger * 138eeaf61d8891f9c9ed12c1a667e72bf83f0857954stephen hemminger * NO locks, but rcu_read_lock 139cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger */ 1407c85fbf0657f216557b0c9c4a2e4e07f37d8bb8cPatrick McHardyvoid br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb, 1417c85fbf0657f216557b0c9c4a2e4e07f37d8bb8cPatrick McHardy struct net_device *dev) 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 143cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger const unsigned char *dest = eth_hdr(skb)->h_dest; 144f350a0a87374418635689471606454abc7beaa3aJiri Pirko struct net_bridge_port *p; 145b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger struct net_bridge *br; 146cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger const unsigned char *buf; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 148cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger if (!pskb_may_pull(skb, 4)) 149cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger goto err; 150cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger 151cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger /* compare of protocol id and version */ 152cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger buf = skb->data; 153cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger if (buf[0] != 0 || buf[1] != 0 || buf[2] != 0) 154cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger goto err; 155b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger 156859828c0ea476b42f3a93d69d117aaba90994b6fJiri Pirko p = br_port_get_check_rcu(dev); 157b5ed54e94d324f17c97852296d61a143f01b227astephen hemminger if (!p) 158b5ed54e94d324f17c97852296d61a143f01b227astephen hemminger goto err; 159b5ed54e94d324f17c97852296d61a143f01b227astephen hemminger 160cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger br = p->br; 161cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger spin_lock(&br->lock); 162b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger 1639cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger if (br->stp_enabled != BR_KERNEL_STP) 1649cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger goto out; 1659cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger 1669cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger if (!(br->dev->flags & IFF_UP)) 1679cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger goto out; 1689cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger 1699cde070874b822d4677f4f01fe146991785813b1Stephen Hemminger if (p->state == BR_STATE_DISABLED) 170b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger goto out; 17185967bb46dd1f8f2c49b85a313866c00ac0c9b59Stephen Hemminger 1729a7b6ef9b9938a1f5cb91ccc0b713b9443edc79fJoe Perches if (!ether_addr_equal(dest, br->group_addr)) 173b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger goto out; 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 175a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger if (p->flags & BR_BPDU_GUARD) { 176a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger br_notice(br, "BPDU received on blocked port %u(%s)\n", 177a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger (unsigned int) p->port_no, p->dev->name); 178a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger br_stp_disable_port(p); 179a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger goto out; 180a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger } 181a2e01a65cd7135dab26d27d4b589b2e5358bec99stephen hemminger 182cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger buf = skb_pull(skb, 3); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (buf[0] == BPDU_TYPE_CONFIG) { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct br_config_bpdu bpdu; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!pskb_may_pull(skb, 32)) 188cf0f02d04a830c8202e6a8f8bb37acc6c1629a91Stephen Hemminger goto out; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf = skb->data; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.topology_change = (buf[1] & 0x01) ? 1 : 0; 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.topology_change_ack = (buf[1] & 0x80) ? 1 : 0; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.prio[0] = buf[2]; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.prio[1] = buf[3]; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[0] = buf[4]; 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[1] = buf[5]; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[2] = buf[6]; 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[3] = buf[7]; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[4] = buf[8]; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root.addr[5] = buf[9]; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.root_path_cost = 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (buf[10] << 24) | 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (buf[11] << 16) | 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (buf[12] << 8) | 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[13]; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.prio[0] = buf[14]; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.prio[1] = buf[15]; 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[0] = buf[16]; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[1] = buf[17]; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[2] = buf[18]; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[3] = buf[19]; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[4] = buf[20]; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.bridge_id.addr[5] = buf[21]; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.port_id = (buf[22] << 8) | buf[23]; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.message_age = br_get_ticks(buf+24); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.max_age = br_get_ticks(buf+26); 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.hello_time = br_get_ticks(buf+28); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bpdu.forward_delay = br_get_ticks(buf+30); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2220652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger if (bpdu.message_age > bpdu.max_age) { 2230652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger if (net_ratelimit()) 2240652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger br_notice(p->br, 2250652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger "port %u config from %pM" 2260652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger " (message_age %ul > max_age %ul)\n", 2270652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger p->port_no, 2280652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger eth_hdr(skb)->h_source, 2290652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger bpdu.message_age, bpdu.max_age); 2300652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger goto out; 2310652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger } 2320652cac22ce3fa0c90e35d0a2862969fc394cb02stephen hemminger 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds br_received_config_bpdu(p, &bpdu); 234160d73b8455edb1a12967e207790b1a93a4cb0e1stephen hemminger } else if (buf[0] == BPDU_TYPE_TCN) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds br_received_tcn_bpdu(p); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out: 238b3f1be4b5412e34647764457bec901e06b03e624Stephen Hemminger spin_unlock(&br->lock); 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err: 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree_skb(skb); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 242