diff options
Diffstat (limited to 'net/batman-adv/bridge_loop_avoidance.c')
-rw-r--r-- | net/batman-adv/bridge_loop_avoidance.c | 121 |
1 files changed, 115 insertions, 6 deletions
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 4f6b44a5b12..1cf18ac44ba 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <net/arp.h> | 33 | #include <net/arp.h> |
34 | #include <linux/if_vlan.h> | 34 | #include <linux/if_vlan.h> |
35 | 35 | ||
36 | static const uint8_t claim_dest[6] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; | ||
37 | static const uint8_t announce_mac[4] = {0x43, 0x05, 0x43, 0x05}; | 36 | static const uint8_t announce_mac[4] = {0x43, 0x05, 0x43, 0x05}; |
38 | 37 | ||
39 | static void bla_periodic_work(struct work_struct *work); | 38 | static void bla_periodic_work(struct work_struct *work); |
@@ -265,7 +264,8 @@ static void bla_send_claim(struct bat_priv *bat_priv, uint8_t *mac, | |||
265 | if (!primary_if) | 264 | if (!primary_if) |
266 | return; | 265 | return; |
267 | 266 | ||
268 | memcpy(&local_claim_dest, claim_dest, sizeof(local_claim_dest)); | 267 | memcpy(&local_claim_dest, &bat_priv->claim_dest, |
268 | sizeof(local_claim_dest)); | ||
269 | local_claim_dest.type = claimtype; | 269 | local_claim_dest.type = claimtype; |
270 | 270 | ||
271 | soft_iface = primary_if->soft_iface; | 271 | soft_iface = primary_if->soft_iface; |
@@ -282,6 +282,7 @@ static void bla_send_claim(struct bat_priv *bat_priv, uint8_t *mac, | |||
282 | primary_if->net_dev->dev_addr, | 282 | primary_if->net_dev->dev_addr, |
283 | /* HW DST: FF:43:05:XX:00:00 | 283 | /* HW DST: FF:43:05:XX:00:00 |
284 | * with XX = claim type | 284 | * with XX = claim type |
285 | * and YY:YY = group id | ||
285 | */ | 286 | */ |
286 | (uint8_t *)&local_claim_dest); | 287 | (uint8_t *)&local_claim_dest); |
287 | 288 | ||
@@ -734,6 +735,86 @@ static int handle_claim(struct bat_priv *bat_priv, | |||
734 | 735 | ||
735 | /** | 736 | /** |
736 | * @bat_priv: the bat priv with all the soft interface information | 737 | * @bat_priv: the bat priv with all the soft interface information |
738 | * @bat_priv: the bat priv with all the soft interface information | ||
739 | * @hw_src: the Hardware source in the ARP Header | ||
740 | * @hw_dst: the Hardware destination in the ARP Header | ||
741 | * @ethhdr: pointer to the Ethernet header of the claim frame | ||
742 | * | ||
743 | * checks if it is a claim packet and if its on the same group. | ||
744 | * This function also applies the group ID of the sender | ||
745 | * if it is in the same mesh. | ||
746 | * | ||
747 | * returns: | ||
748 | * 2 - if it is a claim packet and on the same group | ||
749 | * 1 - if is a claim packet from another group | ||
750 | * 0 - if it is not a claim packet | ||
751 | */ | ||
752 | static int check_claim_group(struct bat_priv *bat_priv, | ||
753 | struct hard_iface *primary_if, | ||
754 | uint8_t *hw_src, uint8_t *hw_dst, | ||
755 | struct ethhdr *ethhdr) | ||
756 | { | ||
757 | uint8_t *backbone_addr; | ||
758 | struct orig_node *orig_node; | ||
759 | struct bla_claim_dst *bla_dst, *bla_dst_own; | ||
760 | |||
761 | bla_dst = (struct bla_claim_dst *)hw_dst; | ||
762 | bla_dst_own = &bat_priv->claim_dest; | ||
763 | |||
764 | /* check if it is a claim packet in general */ | ||
765 | if (memcmp(bla_dst->magic, bla_dst_own->magic, | ||
766 | sizeof(bla_dst->magic)) != 0) | ||
767 | return 0; | ||
768 | |||
769 | /* if announcement packet, use the source, | ||
770 | * otherwise assume it is in the hw_src | ||
771 | */ | ||
772 | switch (bla_dst->type) { | ||
773 | case CLAIM_TYPE_ADD: | ||
774 | backbone_addr = hw_src; | ||
775 | break; | ||
776 | case CLAIM_TYPE_REQUEST: | ||
777 | case CLAIM_TYPE_ANNOUNCE: | ||
778 | case CLAIM_TYPE_DEL: | ||
779 | backbone_addr = ethhdr->h_source; | ||
780 | break; | ||
781 | default: | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* don't accept claim frames from ourselves */ | ||
786 | if (compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) | ||
787 | return 0; | ||
788 | |||
789 | /* if its already the same group, it is fine. */ | ||
790 | if (bla_dst->group == bla_dst_own->group) | ||
791 | return 2; | ||
792 | |||
793 | /* lets see if this originator is in our mesh */ | ||
794 | orig_node = orig_hash_find(bat_priv, backbone_addr); | ||
795 | |||
796 | /* dont accept claims from gateways which are not in | ||
797 | * the same mesh or group. | ||
798 | */ | ||
799 | if (!orig_node) | ||
800 | return 1; | ||
801 | |||
802 | /* if our mesh friends mac is bigger, use it for ourselves. */ | ||
803 | if (ntohs(bla_dst->group) > ntohs(bla_dst_own->group)) { | ||
804 | bat_dbg(DBG_BLA, bat_priv, | ||
805 | "taking other backbones claim group: %04x\n", | ||
806 | ntohs(bla_dst->group)); | ||
807 | bla_dst_own->group = bla_dst->group; | ||
808 | } | ||
809 | |||
810 | orig_node_free_ref(orig_node); | ||
811 | |||
812 | return 2; | ||
813 | } | ||
814 | |||
815 | |||
816 | /** | ||
817 | * @bat_priv: the bat priv with all the soft interface information | ||
737 | * @skb: the frame to be checked | 818 | * @skb: the frame to be checked |
738 | * | 819 | * |
739 | * Check if this is a claim frame, and process it accordingly. | 820 | * Check if this is a claim frame, and process it accordingly. |
@@ -753,6 +834,7 @@ static int bla_process_claim(struct bat_priv *bat_priv, | |||
753 | uint16_t proto; | 834 | uint16_t proto; |
754 | int headlen; | 835 | int headlen; |
755 | short vid = -1; | 836 | short vid = -1; |
837 | int ret; | ||
756 | 838 | ||
757 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 839 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
758 | 840 | ||
@@ -796,8 +878,14 @@ static int bla_process_claim(struct bat_priv *bat_priv, | |||
796 | bla_dst = (struct bla_claim_dst *)hw_dst; | 878 | bla_dst = (struct bla_claim_dst *)hw_dst; |
797 | 879 | ||
798 | /* check if it is a claim frame. */ | 880 | /* check if it is a claim frame. */ |
799 | if (memcmp(hw_dst, claim_dest, 3) != 0) | 881 | ret = check_claim_group(bat_priv, primary_if, hw_src, hw_dst, ethhdr); |
800 | return 0; | 882 | if (ret == 1) |
883 | bat_dbg(DBG_BLA, bat_priv, | ||
884 | "bla_process_claim(): received a claim frame from another group. From: %pM on vid %d ...(hw_src %pM, hw_dst %pM)\n", | ||
885 | ethhdr->h_source, vid, hw_src, hw_dst); | ||
886 | |||
887 | if (ret < 2) | ||
888 | return ret; | ||
801 | 889 | ||
802 | /* become a backbone gw ourselves on this vlan if not happened yet */ | 890 | /* become a backbone gw ourselves on this vlan if not happened yet */ |
803 | bla_update_own_backbone_gw(bat_priv, primary_if, vid); | 891 | bla_update_own_backbone_gw(bat_priv, primary_if, vid); |
@@ -944,6 +1032,10 @@ void bla_update_orig_address(struct bat_priv *bat_priv, | |||
944 | struct hashtable_t *hash; | 1032 | struct hashtable_t *hash; |
945 | int i; | 1033 | int i; |
946 | 1034 | ||
1035 | /* reset bridge loop avoidance group id */ | ||
1036 | bat_priv->claim_dest.group = | ||
1037 | htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); | ||
1038 | |||
947 | if (!oldif) { | 1039 | if (!oldif) { |
948 | bla_purge_claims(bat_priv, NULL, 1); | 1040 | bla_purge_claims(bat_priv, NULL, 1); |
949 | bla_purge_backbone_gw(bat_priv, 1); | 1041 | bla_purge_backbone_gw(bat_priv, 1); |
@@ -1042,9 +1134,24 @@ out: | |||
1042 | int bla_init(struct bat_priv *bat_priv) | 1134 | int bla_init(struct bat_priv *bat_priv) |
1043 | { | 1135 | { |
1044 | int i; | 1136 | int i; |
1137 | uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; | ||
1138 | struct hard_iface *primary_if; | ||
1045 | 1139 | ||
1046 | bat_dbg(DBG_BLA, bat_priv, "bla hash registering\n"); | 1140 | bat_dbg(DBG_BLA, bat_priv, "bla hash registering\n"); |
1047 | 1141 | ||
1142 | /* setting claim destination address */ | ||
1143 | memcpy(&bat_priv->claim_dest.magic, claim_dest, 3); | ||
1144 | bat_priv->claim_dest.type = 0; | ||
1145 | primary_if = primary_if_get_selected(bat_priv); | ||
1146 | if (primary_if) { | ||
1147 | bat_priv->claim_dest.group = | ||
1148 | htons(crc16(0, primary_if->net_dev->dev_addr, | ||
1149 | ETH_ALEN)); | ||
1150 | hardif_free_ref(primary_if); | ||
1151 | } else { | ||
1152 | bat_priv->claim_dest.group = 0; /* will be set later */ | ||
1153 | } | ||
1154 | |||
1048 | /* initialize the duplicate list */ | 1155 | /* initialize the duplicate list */ |
1049 | for (i = 0; i < DUPLIST_SIZE; i++) | 1156 | for (i = 0; i < DUPLIST_SIZE; i++) |
1050 | bat_priv->bcast_duplist[i].entrytime = | 1157 | bat_priv->bcast_duplist[i].entrytime = |
@@ -1448,8 +1555,10 @@ int bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1448 | goto out; | 1555 | goto out; |
1449 | } | 1556 | } |
1450 | 1557 | ||
1451 | seq_printf(seq, "Claims announced for the mesh %s (orig %pM)\n", | 1558 | seq_printf(seq, |
1452 | net_dev->name, primary_if->net_dev->dev_addr); | 1559 | "Claims announced for the mesh %s (orig %pM, group id %04x)\n", |
1560 | net_dev->name, primary_if->net_dev->dev_addr, | ||
1561 | ntohs(bat_priv->claim_dest.group)); | ||
1453 | seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", | 1562 | seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", |
1454 | "Client", "VID", "Originator", "CRC"); | 1563 | "Client", "VID", "Originator", "CRC"); |
1455 | for (i = 0; i < hash->size; i++) { | 1564 | for (i = 0; i < hash->size; i++) { |