2 * Copied from Linux Monitor (LiMon) - Networking.
4 * Copyright 1994 - 2000 Neil Russell.
6 * Copyright 2000 Roland Borde
7 * Copyright 2000 Paolo Scaffardi
8 * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
13 #if defined(CONFIG_CDP_VERSION)
14 #include <timestamp.h>
19 /* Ethernet bcast address */
20 const uchar NetCDPAddr
[6] = { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };
22 #define CDP_DEVICE_ID_TLV 0x0001
23 #define CDP_ADDRESS_TLV 0x0002
24 #define CDP_PORT_ID_TLV 0x0003
25 #define CDP_CAPABILITIES_TLV 0x0004
26 #define CDP_VERSION_TLV 0x0005
27 #define CDP_PLATFORM_TLV 0x0006
28 #define CDP_NATIVE_VLAN_TLV 0x000a
29 #define CDP_APPLIANCE_VLAN_TLV 0x000e
30 #define CDP_TRIGGER_TLV 0x000f
31 #define CDP_POWER_CONSUMPTION_TLV 0x0010
32 #define CDP_SYSNAME_TLV 0x0014
33 #define CDP_SYSOBJECT_TLV 0x0015
34 #define CDP_MANAGEMENT_ADDRESS_TLV 0x0016
36 #define CDP_TIMEOUT 250UL /* one packet every 250ms */
42 ushort CDPApplianceVLAN
;
44 static const uchar CDP_SNAP_hdr
[8] = {
45 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 };
48 CDP_compute_csum(const uchar
*buff
, ushort len
)
57 odd
= 1 & (ulong
)buff
;
67 if (result
& 0x80000000)
68 result
= (result
& 0xFFFF) + (result
>> 16);
72 leftover
= (signed short)(*(const signed char *)buff
);
74 * CISCO SUCKS big time! (and blows too):
75 * CDP uses the IP checksum algorithm with a twist;
76 * for the last byte it *sign* extends and sums.
78 result
= (result
& 0xffff0000) |
79 ((result
+ leftover
) & 0x0000ffff);
82 result
= (result
& 0xFFFF) + (result
>> 16);
85 result
= ((result
>> 8) & 0xff) |
86 ((result
& 0xff) << 8);
89 /* add up 16-bit and 17-bit words for 17+c bits */
90 result
= (result
& 0xffff) + (result
>> 16);
91 /* add up 16-bit and 2-bit for 16+c bit */
92 result
= (result
& 0xffff) + (result
>> 16);
94 result
= (result
& 0xffff) + (result
>> 16);
97 csum
= ~(ushort
)result
;
99 /* run time endian detection */
100 if (csum
!= htons(csum
)) /* little endian */
112 struct ethernet_hdr
*et
;
115 #if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \
116 defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM)
121 et
= (struct ethernet_hdr
*)pkt
;
123 /* NOTE: trigger sent not on any VLAN */
125 /* form ethernet header */
126 memcpy(et
->et_dest
, NetCDPAddr
, 6);
127 memcpy(et
->et_src
, NetOurEther
, 6);
129 pkt
+= ETHER_HDR_SIZE
;
132 memcpy((uchar
*)pkt
, CDP_SNAP_hdr
, sizeof(CDP_SNAP_hdr
));
133 pkt
+= sizeof(CDP_SNAP_hdr
);
136 *pkt
++ = 0x02; /* CDP version 2 */
137 *pkt
++ = 180; /* TTL */
140 /* checksum (0 for later calculation) */
144 #ifdef CONFIG_CDP_DEVICE_ID
145 *s
++ = htons(CDP_DEVICE_ID_TLV
);
146 *s
++ = htons(CONFIG_CDP_DEVICE_ID
);
147 sprintf(buf
, CONFIG_CDP_DEVICE_ID_PREFIX
"%pm", NetOurEther
);
148 memcpy((uchar
*)s
, buf
, 16);
152 #ifdef CONFIG_CDP_PORT_ID
153 *s
++ = htons(CDP_PORT_ID_TLV
);
154 memset(buf
, 0, sizeof(buf
));
155 sprintf(buf
, CONFIG_CDP_PORT_ID
, eth_get_dev_index());
157 if (len
& 1) /* make it even */
159 *s
++ = htons(len
+ 4);
160 memcpy((uchar
*)s
, buf
, len
);
164 #ifdef CONFIG_CDP_CAPABILITIES
165 *s
++ = htons(CDP_CAPABILITIES_TLV
);
167 *(ulong
*)s
= htonl(CONFIG_CDP_CAPABILITIES
);
171 #ifdef CONFIG_CDP_VERSION
172 *s
++ = htons(CDP_VERSION_TLV
);
173 memset(buf
, 0, sizeof(buf
));
174 strcpy(buf
, CONFIG_CDP_VERSION
);
176 if (len
& 1) /* make it even */
178 *s
++ = htons(len
+ 4);
179 memcpy((uchar
*)s
, buf
, len
);
183 #ifdef CONFIG_CDP_PLATFORM
184 *s
++ = htons(CDP_PLATFORM_TLV
);
185 memset(buf
, 0, sizeof(buf
));
186 strcpy(buf
, CONFIG_CDP_PLATFORM
);
188 if (len
& 1) /* make it even */
190 *s
++ = htons(len
+ 4);
191 memcpy((uchar
*)s
, buf
, len
);
195 #ifdef CONFIG_CDP_TRIGGER
196 *s
++ = htons(CDP_TRIGGER_TLV
);
198 *(ulong
*)s
= htonl(CONFIG_CDP_TRIGGER
);
202 #ifdef CONFIG_CDP_POWER_CONSUMPTION
203 *s
++ = htons(CDP_POWER_CONSUMPTION_TLV
);
205 *s
++ = htons(CONFIG_CDP_POWER_CONSUMPTION
);
208 /* length of ethernet packet */
209 len
= (uchar
*)s
- ((uchar
*)NetTxPacket
+ ETHER_HDR_SIZE
);
210 et
->et_protlen
= htons(len
);
212 len
= ETHER_HDR_SIZE
+ sizeof(CDP_SNAP_hdr
);
213 chksum
= CDP_compute_csum((uchar
*)NetTxPacket
+ len
,
214 (uchar
*)s
- (NetTxPacket
+ len
));
219 NetSendPacket(NetTxPacket
, (uchar
*)s
- NetTxPacket
);
229 NetSetTimeout(CDP_TIMEOUT
, CDPTimeout
);
234 /* if not OK try again */
238 NetState
= NETLOOP_SUCCESS
;
242 CDPDummyHandler(uchar
*pkt
, unsigned dest
, IPaddr_t sip
, unsigned src
,
248 void cdp_receive(const uchar
*pkt
, unsigned len
)
256 if (len
< sizeof(CDP_SNAP_hdr
) + 4)
259 /* check for valid CDP SNAP header */
260 if (memcmp(pkt
, CDP_SNAP_hdr
, sizeof(CDP_SNAP_hdr
)) != 0)
263 pkt
+= sizeof(CDP_SNAP_hdr
);
264 len
-= sizeof(CDP_SNAP_hdr
);
266 /* Version of CDP protocol must be >= 2 and TTL != 0 */
267 if (pkt
[0] < 0x02 || pkt
[1] == 0)
271 * if version is greater than 0x02 maybe we'll have a problem;
275 printf("**WARNING: CDP packet received with a protocol version "
276 "%d > 2\n", pkt
[0] & 0xff);
278 if (CDP_compute_csum(pkt
, len
) != 0)
290 ss
= (const ushort
*)pkt
;
299 ss
+= 2; /* point ss to the data of the TLV */
303 case CDP_DEVICE_ID_TLV
:
305 case CDP_ADDRESS_TLV
:
307 case CDP_PORT_ID_TLV
:
309 case CDP_CAPABILITIES_TLV
:
311 case CDP_VERSION_TLV
:
313 case CDP_PLATFORM_TLV
:
315 case CDP_NATIVE_VLAN_TLV
:
318 case CDP_APPLIANCE_VLAN_TLV
:
319 t
= (const uchar
*)ss
;
324 ss
= (const ushort
*)(t
+ 1);
326 #ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE
327 if (t
[0] == CONFIG_CDP_APPLIANCE_VLAN_TYPE
)
330 /* XXX will this work; dunno */
336 case CDP_TRIGGER_TLV
:
338 case CDP_POWER_CONSUMPTION_TLV
:
340 case CDP_SYSNAME_TLV
:
342 case CDP_SYSOBJECT_TLV
:
344 case CDP_MANAGEMENT_ADDRESS_TLV
:
349 CDPApplianceVLAN
= vlan
;
350 CDPNativeVLAN
= nvlan
;
356 printf("** CDP packet is too short\n");
363 printf("Using %s device\n", eth_get_name());
367 CDPNativeVLAN
= htons(-1);
368 CDPApplianceVLAN
= htons(-1);
370 NetSetTimeout(CDP_TIMEOUT
, CDPTimeout
);
371 NetSetHandler(CDPDummyHandler
);