aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh.c
diff options
context:
space:
mode:
authorJavier Cardona <javier@cozybit.com>2009-08-10 15:15:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:14:00 -0400
commit3c5772a5279de9eadfff7adb5ddea08106495fff (patch)
tree297772521c18283ccfa19aacb090f396fa2b399e /net/mac80211/mesh.c
parenta9e3091bf08ddea35f172549a8a21d5bd6ee6129 (diff)
mac80211: Use 3-address format for mesh broadcast frames.
The 11s task group recently changed the frame mesh multicast/broadcast frame format to use 3-address. This was done to avoid interactions with widely deployed lazy-WDS access points. This patch changes the format of group addressed frames, both mesh-originated and proxied, to use the data format defined in draft D2.08 and forward. The address fields used for group addressed frames is: In 802.11 header ToDS:0 FromDS:1 addr1: DA (broadcast/multicast address) addr2: TA addr3: Mesh SA In address extension header: addr4: SA (only present if frame was proxied) Note that this change breaks backward compatibility with earlier mesh stack versions. Signed-off-by: Andrey Yurovsky <andrey@cozybit.com> Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/mesh.c')
-rw-r--r--net/mac80211/mesh.c62
1 files changed, 58 insertions, 4 deletions
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8c068e215fb8..10d93386042a 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -399,21 +399,75 @@ endgrow:
399} 399}
400 400
401/** 401/**
402 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
403 * @hdr: 802.11 frame header
404 * @fc: frame control field
405 * @meshda: destination address in the mesh
406 * @meshsa: source address address in the mesh. Same as TA, as frame is
407 * locally originated.
408 *
409 * Return the length of the 802.11 (does not include a mesh control header)
410 */
411int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
412 *meshda, char *meshsa) {
413 if (is_multicast_ether_addr(meshda)) {
414 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
415 /* DA TA SA */
416 memcpy(hdr->addr1, meshda, ETH_ALEN);
417 memcpy(hdr->addr2, meshsa, ETH_ALEN);
418 memcpy(hdr->addr3, meshsa, ETH_ALEN);
419 return 24;
420 } else {
421 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
422 IEEE80211_FCTL_TODS);
423 /* RA TA DA SA */
424 memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
425 memcpy(hdr->addr2, meshsa, ETH_ALEN);
426 memcpy(hdr->addr3, meshda, ETH_ALEN);
427 memcpy(hdr->addr4, meshsa, ETH_ALEN);
428 return 30;
429 }
430}
431
432/**
402 * ieee80211_new_mesh_header - create a new mesh header 433 * ieee80211_new_mesh_header - create a new mesh header
403 * @meshhdr: uninitialized mesh header 434 * @meshhdr: uninitialized mesh header
404 * @sdata: mesh interface to be used 435 * @sdata: mesh interface to be used
436 * @addr4: addr4 of the mesh frame (1st in ae header)
437 * may be NULL
438 * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
439 * may be NULL unless addr6 is present
440 * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
441 * may be NULL unless addr5 is present
405 * 442 *
406 * Return the header length. 443 * Return the header length.
407 */ 444 */
408int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 445int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
409 struct ieee80211_sub_if_data *sdata) 446 struct ieee80211_sub_if_data *sdata, char *addr4,
447 char *addr5, char *addr6)
410{ 448{
411 meshhdr->flags = 0; 449 int aelen = 0;
450 memset(meshhdr, 0, sizeof(meshhdr));
412 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; 451 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
413 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); 452 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
414 sdata->u.mesh.mesh_seqnum++; 453 sdata->u.mesh.mesh_seqnum++;
415 454 if (addr4) {
416 return 6; 455 meshhdr->flags |= MESH_FLAGS_AE_A4;
456 aelen += ETH_ALEN;
457 memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
458 }
459 if (addr5 && addr6) {
460 meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
461 aelen += 2 * ETH_ALEN;
462 if (!addr4) {
463 memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
464 memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
465 } else {
466 memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
467 memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
468 }
469 }
470 return 6 + aelen;
417} 471}
418 472
419static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, 473static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,