diff options
author | Javier Cardona <javier@cozybit.com> | 2009-08-10 15:15:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-08-14 09:14:00 -0400 |
commit | 3c5772a5279de9eadfff7adb5ddea08106495fff (patch) | |
tree | 297772521c18283ccfa19aacb090f396fa2b399e /net/mac80211/mesh.c | |
parent | a9e3091bf08ddea35f172549a8a21d5bd6ee6129 (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.c | 62 |
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 | */ | ||
411 | int 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 | */ |
408 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 445 | int 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 | ||
419 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 473 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, |