diff options
Diffstat (limited to 'drivers/staging')
-rw-r--r-- | drivers/staging/batman-adv/bat_sysfs.c | 55 | ||||
-rw-r--r-- | drivers/staging/batman-adv/hard-interface.c | 34 | ||||
-rw-r--r-- | drivers/staging/batman-adv/originator.c | 10 | ||||
-rw-r--r-- | drivers/staging/batman-adv/packet.h | 26 | ||||
-rw-r--r-- | drivers/staging/batman-adv/routing.c | 115 | ||||
-rw-r--r-- | drivers/staging/batman-adv/routing.h | 1 | ||||
-rw-r--r-- | drivers/staging/batman-adv/soft-interface.c | 4 | ||||
-rw-r--r-- | drivers/staging/batman-adv/types.h | 10 | ||||
-rw-r--r-- | drivers/staging/batman-adv/unicast.c | 177 | ||||
-rw-r--r-- | drivers/staging/batman-adv/unicast.h | 12 |
10 files changed, 416 insertions, 28 deletions
diff --git a/drivers/staging/batman-adv/bat_sysfs.c b/drivers/staging/batman-adv/bat_sysfs.c index d49addeb0ad..b9fe391b641 100644 --- a/drivers/staging/batman-adv/bat_sysfs.c +++ b/drivers/staging/batman-adv/bat_sysfs.c | |||
@@ -134,6 +134,58 @@ static ssize_t store_bond(struct kobject *kobj, struct attribute *attr, | |||
134 | return count; | 134 | return count; |
135 | } | 135 | } |
136 | 136 | ||
137 | static ssize_t show_frag(struct kobject *kobj, struct attribute *attr, | ||
138 | char *buff) | ||
139 | { | ||
140 | struct device *dev = to_dev(kobj->parent); | ||
141 | struct bat_priv *bat_priv = netdev_priv(to_net_dev(dev)); | ||
142 | int frag_status = atomic_read(&bat_priv->frag_enabled); | ||
143 | |||
144 | return sprintf(buff, "%s\n", | ||
145 | frag_status == 0 ? "disabled" : "enabled"); | ||
146 | } | ||
147 | |||
148 | static ssize_t store_frag(struct kobject *kobj, struct attribute *attr, | ||
149 | char *buff, size_t count) | ||
150 | { | ||
151 | struct device *dev = to_dev(kobj->parent); | ||
152 | struct net_device *net_dev = to_net_dev(dev); | ||
153 | struct bat_priv *bat_priv = netdev_priv(net_dev); | ||
154 | int frag_enabled_tmp = -1; | ||
155 | |||
156 | if (((count == 2) && (buff[0] == '1')) || | ||
157 | (strncmp(buff, "enable", 6) == 0)) | ||
158 | frag_enabled_tmp = 1; | ||
159 | |||
160 | if (((count == 2) && (buff[0] == '0')) || | ||
161 | (strncmp(buff, "disable", 7) == 0)) | ||
162 | frag_enabled_tmp = 0; | ||
163 | |||
164 | if (frag_enabled_tmp < 0) { | ||
165 | if (buff[count - 1] == '\n') | ||
166 | buff[count - 1] = '\0'; | ||
167 | |||
168 | bat_err(net_dev, | ||
169 | "Invalid parameter for 'fragmentation' setting on mesh" | ||
170 | "received: %s\n", buff); | ||
171 | return -EINVAL; | ||
172 | } | ||
173 | |||
174 | if (atomic_read(&bat_priv->frag_enabled) == frag_enabled_tmp) | ||
175 | return count; | ||
176 | |||
177 | bat_info(net_dev, "Changing fragmentation from: %s to: %s\n", | ||
178 | atomic_read(&bat_priv->frag_enabled) == 1 ? | ||
179 | "enabled" : "disabled", | ||
180 | frag_enabled_tmp == 1 ? "enabled" : "disabled"); | ||
181 | |||
182 | atomic_set(&bat_priv->frag_enabled, (unsigned)frag_enabled_tmp); | ||
183 | |||
184 | update_min_mtu(); | ||
185 | |||
186 | return count; | ||
187 | } | ||
188 | |||
137 | static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, | 189 | static ssize_t show_vis_mode(struct kobject *kobj, struct attribute *attr, |
138 | char *buff) | 190 | char *buff) |
139 | { | 191 | { |
@@ -279,6 +331,7 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr, | |||
279 | static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR, | 331 | static BAT_ATTR(aggregated_ogms, S_IRUGO | S_IWUSR, |
280 | show_aggr_ogms, store_aggr_ogms); | 332 | show_aggr_ogms, store_aggr_ogms); |
281 | static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond); | 333 | static BAT_ATTR(bonding, S_IRUGO | S_IWUSR, show_bond, store_bond); |
334 | static BAT_ATTR(fragmentation, S_IRUGO | S_IWUSR, show_frag, store_frag); | ||
282 | static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); | 335 | static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); |
283 | static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, | 336 | static BAT_ATTR(orig_interval, S_IRUGO | S_IWUSR, |
284 | show_orig_interval, store_orig_interval); | 337 | show_orig_interval, store_orig_interval); |
@@ -289,6 +342,7 @@ static BAT_ATTR(log_level, S_IRUGO | S_IWUSR, show_log_level, store_log_level); | |||
289 | static struct bat_attribute *mesh_attrs[] = { | 342 | static struct bat_attribute *mesh_attrs[] = { |
290 | &bat_attr_aggregated_ogms, | 343 | &bat_attr_aggregated_ogms, |
291 | &bat_attr_bonding, | 344 | &bat_attr_bonding, |
345 | &bat_attr_fragmentation, | ||
292 | &bat_attr_vis_mode, | 346 | &bat_attr_vis_mode, |
293 | &bat_attr_orig_interval, | 347 | &bat_attr_orig_interval, |
294 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 348 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
@@ -308,6 +362,7 @@ int sysfs_add_meshif(struct net_device *dev) | |||
308 | routine as soon as we have it */ | 362 | routine as soon as we have it */ |
309 | atomic_set(&bat_priv->aggregation_enabled, 1); | 363 | atomic_set(&bat_priv->aggregation_enabled, 1); |
310 | atomic_set(&bat_priv->bonding_enabled, 0); | 364 | atomic_set(&bat_priv->bonding_enabled, 0); |
365 | atomic_set(&bat_priv->frag_enabled, 1); | ||
311 | atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); | 366 | atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); |
312 | atomic_set(&bat_priv->orig_interval, 1000); | 367 | atomic_set(&bat_priv->orig_interval, 1000); |
313 | atomic_set(&bat_priv->log_level, 0); | 368 | atomic_set(&bat_priv->log_level, 0); |
diff --git a/drivers/staging/batman-adv/hard-interface.c b/drivers/staging/batman-adv/hard-interface.c index 6e973a79aa2..82d3d554467 100644 --- a/drivers/staging/batman-adv/hard-interface.c +++ b/drivers/staging/batman-adv/hard-interface.c | |||
@@ -166,6 +166,11 @@ int hardif_min_mtu(void) | |||
166 | /* allow big frames if all devices are capable to do so | 166 | /* allow big frames if all devices are capable to do so |
167 | * (have MTU > 1500 + BAT_HEADER_LEN) */ | 167 | * (have MTU > 1500 + BAT_HEADER_LEN) */ |
168 | int min_mtu = ETH_DATA_LEN; | 168 | int min_mtu = ETH_DATA_LEN; |
169 | /* FIXME: each batman_if will be attached to a softif */ | ||
170 | struct bat_priv *bat_priv = netdev_priv(soft_device); | ||
171 | |||
172 | if (atomic_read(&bat_priv->frag_enabled)) | ||
173 | goto out; | ||
169 | 174 | ||
170 | rcu_read_lock(); | 175 | rcu_read_lock(); |
171 | list_for_each_entry_rcu(batman_if, &if_list, list) { | 176 | list_for_each_entry_rcu(batman_if, &if_list, list) { |
@@ -175,7 +180,7 @@ int hardif_min_mtu(void) | |||
175 | min_mtu); | 180 | min_mtu); |
176 | } | 181 | } |
177 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
178 | 183 | out: | |
179 | return min_mtu; | 184 | return min_mtu; |
180 | } | 185 | } |
181 | 186 | ||
@@ -261,8 +266,30 @@ int hardif_enable_interface(struct batman_if *batman_if) | |||
261 | orig_hash_add_if(batman_if, bat_priv->num_ifaces); | 266 | orig_hash_add_if(batman_if, bat_priv->num_ifaces); |
262 | 267 | ||
263 | atomic_set(&batman_if->seqno, 1); | 268 | atomic_set(&batman_if->seqno, 1); |
269 | atomic_set(&batman_if->frag_seqno, 1); | ||
264 | bat_info(soft_device, "Adding interface: %s\n", batman_if->dev); | 270 | bat_info(soft_device, "Adding interface: %s\n", batman_if->dev); |
265 | 271 | ||
272 | if (atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < | ||
273 | ETH_DATA_LEN + BAT_HEADER_LEN) | ||
274 | bat_info(soft_device, | ||
275 | "The MTU of interface %s is too small (%i) to handle " | ||
276 | "the transport of batman-adv packets. Packets going " | ||
277 | "over this interface will be fragmented on layer2 " | ||
278 | "which could impact the performance. Setting the MTU " | ||
279 | "to %zi would solve the problem.\n", | ||
280 | batman_if->dev, batman_if->net_dev->mtu, | ||
281 | ETH_DATA_LEN + BAT_HEADER_LEN); | ||
282 | |||
283 | if (!atomic_read(&bat_priv->frag_enabled) && batman_if->net_dev->mtu < | ||
284 | ETH_DATA_LEN + BAT_HEADER_LEN) | ||
285 | bat_info(soft_device, | ||
286 | "The MTU of interface %s is too small (%i) to handle " | ||
287 | "the transport of batman-adv packets. If you experience" | ||
288 | " problems getting traffic through try increasing the " | ||
289 | "MTU to %zi.\n", | ||
290 | batman_if->dev, batman_if->net_dev->mtu, | ||
291 | ETH_DATA_LEN + BAT_HEADER_LEN); | ||
292 | |||
266 | if (hardif_is_iface_up(batman_if)) | 293 | if (hardif_is_iface_up(batman_if)) |
267 | hardif_activate_interface(soft_device, bat_priv, batman_if); | 294 | hardif_activate_interface(soft_device, bat_priv, batman_if); |
268 | else | 295 | else |
@@ -495,6 +522,11 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | |||
495 | ret = recv_unicast_packet(skb, batman_if); | 522 | ret = recv_unicast_packet(skb, batman_if); |
496 | break; | 523 | break; |
497 | 524 | ||
525 | /* fragmented unicast packet */ | ||
526 | case BAT_UNICAST_FRAG: | ||
527 | ret = recv_ucast_frag_packet(skb, batman_if); | ||
528 | break; | ||
529 | |||
498 | /* broadcast packet */ | 530 | /* broadcast packet */ |
499 | case BAT_BCAST: | 531 | case BAT_BCAST: |
500 | ret = recv_bcast_packet(skb); | 532 | ret = recv_bcast_packet(skb); |
diff --git a/drivers/staging/batman-adv/originator.c b/drivers/staging/batman-adv/originator.c index de5a8c1a810..b51a13ef856 100644 --- a/drivers/staging/batman-adv/originator.c +++ b/drivers/staging/batman-adv/originator.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "translation-table.h" | 27 | #include "translation-table.h" |
28 | #include "routing.h" | 28 | #include "routing.h" |
29 | #include "hard-interface.h" | 29 | #include "hard-interface.h" |
30 | #include "unicast.h" | ||
30 | 31 | ||
31 | static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); | 32 | static DECLARE_DELAYED_WORK(purge_orig_wq, purge_orig); |
32 | 33 | ||
@@ -95,6 +96,7 @@ static void free_orig_node(void *data) | |||
95 | kfree(neigh_node); | 96 | kfree(neigh_node); |
96 | } | 97 | } |
97 | 98 | ||
99 | frag_list_free(&orig_node->frag_list); | ||
98 | hna_global_del_orig(orig_node, "originator timed out"); | 100 | hna_global_del_orig(orig_node, "originator timed out"); |
99 | 101 | ||
100 | kfree(orig_node->bcast_own); | 102 | kfree(orig_node->bcast_own); |
@@ -157,6 +159,10 @@ struct orig_node *get_orig_node(uint8_t *addr) | |||
157 | 159 | ||
158 | size = bat_priv->num_ifaces * sizeof(uint8_t); | 160 | size = bat_priv->num_ifaces * sizeof(uint8_t); |
159 | orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); | 161 | orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC); |
162 | |||
163 | INIT_LIST_HEAD(&orig_node->frag_list); | ||
164 | orig_node->last_frag_packet = 0; | ||
165 | |||
160 | if (!orig_node->bcast_own_sum) | 166 | if (!orig_node->bcast_own_sum) |
161 | goto free_bcast_own; | 167 | goto free_bcast_own; |
162 | 168 | ||
@@ -271,6 +277,10 @@ void purge_orig(struct work_struct *work) | |||
271 | hash_remove_bucket(orig_hash, &hashit); | 277 | hash_remove_bucket(orig_hash, &hashit); |
272 | free_orig_node(orig_node); | 278 | free_orig_node(orig_node); |
273 | } | 279 | } |
280 | |||
281 | if (time_after(jiffies, (orig_node->last_frag_packet + | ||
282 | msecs_to_jiffies(FRAG_TIMEOUT)))) | ||
283 | frag_list_free(&orig_node->frag_list); | ||
274 | } | 284 | } |
275 | 285 | ||
276 | spin_unlock_irqrestore(&orig_hash_lock, flags); | 286 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
diff --git a/drivers/staging/batman-adv/packet.h b/drivers/staging/batman-adv/packet.h index abb5e460f23..44de1bfb0b0 100644 --- a/drivers/staging/batman-adv/packet.h +++ b/drivers/staging/batman-adv/packet.h | |||
@@ -24,14 +24,15 @@ | |||
24 | 24 | ||
25 | #define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ | 25 | #define ETH_P_BATMAN 0x4305 /* unofficial/not registered Ethertype */ |
26 | 26 | ||
27 | #define BAT_PACKET 0x01 | 27 | #define BAT_PACKET 0x01 |
28 | #define BAT_ICMP 0x02 | 28 | #define BAT_ICMP 0x02 |
29 | #define BAT_UNICAST 0x03 | 29 | #define BAT_UNICAST 0x03 |
30 | #define BAT_BCAST 0x04 | 30 | #define BAT_BCAST 0x04 |
31 | #define BAT_VIS 0x05 | 31 | #define BAT_VIS 0x05 |
32 | #define BAT_UNICAST_FRAG 0x06 | ||
32 | 33 | ||
33 | /* this file is included by batctl which needs these defines */ | 34 | /* this file is included by batctl which needs these defines */ |
34 | #define COMPAT_VERSION 11 | 35 | #define COMPAT_VERSION 13 |
35 | #define DIRECTLINK 0x40 | 36 | #define DIRECTLINK 0x40 |
36 | #define VIS_SERVER 0x20 | 37 | #define VIS_SERVER 0x20 |
37 | #define PRIMARIES_FIRST_HOP 0x10 | 38 | #define PRIMARIES_FIRST_HOP 0x10 |
@@ -47,6 +48,9 @@ | |||
47 | #define VIS_TYPE_SERVER_SYNC 0 | 48 | #define VIS_TYPE_SERVER_SYNC 0 |
48 | #define VIS_TYPE_CLIENT_UPDATE 1 | 49 | #define VIS_TYPE_CLIENT_UPDATE 1 |
49 | 50 | ||
51 | /* fragmentation defines */ | ||
52 | #define UNI_FRAG_HEAD 0x01 | ||
53 | |||
50 | struct batman_packet { | 54 | struct batman_packet { |
51 | uint8_t packet_type; | 55 | uint8_t packet_type; |
52 | uint8_t version; /* batman version field */ | 56 | uint8_t version; /* batman version field */ |
@@ -96,6 +100,16 @@ struct unicast_packet { | |||
96 | uint8_t ttl; | 100 | uint8_t ttl; |
97 | } __attribute__((packed)); | 101 | } __attribute__((packed)); |
98 | 102 | ||
103 | struct unicast_frag_packet { | ||
104 | uint8_t packet_type; | ||
105 | uint8_t version; /* batman version field */ | ||
106 | uint8_t dest[6]; | ||
107 | uint8_t ttl; | ||
108 | uint8_t flags; | ||
109 | uint8_t orig[6]; | ||
110 | uint16_t seqno; | ||
111 | } __attribute__((packed)); | ||
112 | |||
99 | struct bcast_packet { | 113 | struct bcast_packet { |
100 | uint8_t packet_type; | 114 | uint8_t packet_type; |
101 | uint8_t version; /* batman version field */ | 115 | uint8_t version; /* batman version field */ |
diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 032195e6de9..d8e77ac21c2 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "ring_buffer.h" | 32 | #include "ring_buffer.h" |
33 | #include "vis.h" | 33 | #include "vis.h" |
34 | #include "aggregation.h" | 34 | #include "aggregation.h" |
35 | #include "unicast.h" | ||
35 | 36 | ||
36 | static DECLARE_WAIT_QUEUE_HEAD(thread_wait); | 37 | static DECLARE_WAIT_QUEUE_HEAD(thread_wait); |
37 | 38 | ||
@@ -1105,43 +1106,43 @@ struct neigh_node *find_router(struct orig_node *orig_node, | |||
1105 | return router; | 1106 | return router; |
1106 | } | 1107 | } |
1107 | 1108 | ||
1108 | int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) | 1109 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) |
1109 | { | 1110 | { |
1110 | struct unicast_packet *unicast_packet; | ||
1111 | struct orig_node *orig_node; | ||
1112 | struct neigh_node *router; | ||
1113 | struct ethhdr *ethhdr; | 1111 | struct ethhdr *ethhdr; |
1114 | struct batman_if *batman_if; | ||
1115 | struct sk_buff *skb_old; | ||
1116 | uint8_t dstaddr[ETH_ALEN]; | ||
1117 | int hdr_size = sizeof(struct unicast_packet); | ||
1118 | unsigned long flags; | ||
1119 | 1112 | ||
1120 | /* drop packet if it has not necessary minimum size */ | 1113 | /* drop packet if it has not necessary minimum size */ |
1121 | if (skb_headlen(skb) < hdr_size) | 1114 | if (skb_headlen(skb) < hdr_size) |
1122 | return NET_RX_DROP; | 1115 | return -1; |
1123 | 1116 | ||
1124 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | 1117 | ethhdr = (struct ethhdr *) skb_mac_header(skb); |
1125 | 1118 | ||
1126 | /* packet with unicast indication but broadcast recipient */ | 1119 | /* packet with unicast indication but broadcast recipient */ |
1127 | if (is_bcast(ethhdr->h_dest)) | 1120 | if (is_bcast(ethhdr->h_dest)) |
1128 | return NET_RX_DROP; | 1121 | return -1; |
1129 | 1122 | ||
1130 | /* packet with broadcast sender address */ | 1123 | /* packet with broadcast sender address */ |
1131 | if (is_bcast(ethhdr->h_source)) | 1124 | if (is_bcast(ethhdr->h_source)) |
1132 | return NET_RX_DROP; | 1125 | return -1; |
1133 | 1126 | ||
1134 | /* not for me */ | 1127 | /* not for me */ |
1135 | if (!is_my_mac(ethhdr->h_dest)) | 1128 | if (!is_my_mac(ethhdr->h_dest)) |
1136 | return NET_RX_DROP; | 1129 | return -1; |
1137 | 1130 | ||
1138 | unicast_packet = (struct unicast_packet *) skb->data; | 1131 | return 0; |
1132 | } | ||
1139 | 1133 | ||
1140 | /* packet for me */ | 1134 | static int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, |
1141 | if (is_my_mac(unicast_packet->dest)) { | 1135 | int hdr_size) |
1142 | interface_rx(skb, hdr_size); | 1136 | { |
1143 | return NET_RX_SUCCESS; | 1137 | struct orig_node *orig_node; |
1144 | } | 1138 | struct neigh_node *router; |
1139 | struct batman_if *batman_if; | ||
1140 | struct sk_buff *skb_old; | ||
1141 | uint8_t dstaddr[ETH_ALEN]; | ||
1142 | unsigned long flags; | ||
1143 | struct unicast_packet *unicast_packet = | ||
1144 | (struct unicast_packet *) skb->data; | ||
1145 | struct ethhdr *ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
1145 | 1146 | ||
1146 | /* TTL exceeded */ | 1147 | /* TTL exceeded */ |
1147 | if (unicast_packet->ttl < 2) { | 1148 | if (unicast_packet->ttl < 2) { |
@@ -1172,7 +1173,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) | |||
1172 | spin_unlock_irqrestore(&orig_hash_lock, flags); | 1173 | spin_unlock_irqrestore(&orig_hash_lock, flags); |
1173 | 1174 | ||
1174 | /* create a copy of the skb, if needed, to modify it. */ | 1175 | /* create a copy of the skb, if needed, to modify it. */ |
1175 | if (!skb_clone_writable(skb, sizeof(struct unicast_packet))) { | 1176 | if (!skb_clone_writable(skb, hdr_size)) { |
1176 | skb_old = skb; | 1177 | skb_old = skb; |
1177 | skb = skb_copy(skb, GFP_ATOMIC); | 1178 | skb = skb_copy(skb, GFP_ATOMIC); |
1178 | if (!skb) | 1179 | if (!skb) |
@@ -1191,6 +1192,80 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) | |||
1191 | return NET_RX_SUCCESS; | 1192 | return NET_RX_SUCCESS; |
1192 | } | 1193 | } |
1193 | 1194 | ||
1195 | int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) | ||
1196 | { | ||
1197 | struct unicast_packet *unicast_packet; | ||
1198 | int hdr_size = sizeof(struct unicast_packet); | ||
1199 | |||
1200 | if (check_unicast_packet(skb, hdr_size) < 0) | ||
1201 | return NET_RX_DROP; | ||
1202 | |||
1203 | unicast_packet = (struct unicast_packet *) skb->data; | ||
1204 | |||
1205 | /* packet for me */ | ||
1206 | if (is_my_mac(unicast_packet->dest)) { | ||
1207 | interface_rx(skb, hdr_size); | ||
1208 | return NET_RX_SUCCESS; | ||
1209 | } | ||
1210 | |||
1211 | return route_unicast_packet(skb, recv_if, hdr_size); | ||
1212 | } | ||
1213 | |||
1214 | int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) | ||
1215 | { | ||
1216 | struct unicast_frag_packet *unicast_packet; | ||
1217 | struct orig_node *orig_node; | ||
1218 | struct frag_packet_list_entry *tmp_frag_entry; | ||
1219 | int hdr_size = sizeof(struct unicast_frag_packet); | ||
1220 | unsigned long flags; | ||
1221 | |||
1222 | if (check_unicast_packet(skb, hdr_size) < 0) | ||
1223 | return NET_RX_DROP; | ||
1224 | |||
1225 | unicast_packet = (struct unicast_frag_packet *) skb->data; | ||
1226 | |||
1227 | /* packet for me */ | ||
1228 | if (is_my_mac(unicast_packet->dest)) { | ||
1229 | |||
1230 | spin_lock_irqsave(&orig_hash_lock, flags); | ||
1231 | orig_node = ((struct orig_node *) | ||
1232 | hash_find(orig_hash, unicast_packet->orig)); | ||
1233 | |||
1234 | if (!orig_node) { | ||
1235 | pr_warning("couldn't find orig node for " | ||
1236 | "fragmentation\n"); | ||
1237 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
1238 | return NET_RX_DROP; | ||
1239 | } | ||
1240 | |||
1241 | orig_node->last_frag_packet = jiffies; | ||
1242 | |||
1243 | if (list_empty(&orig_node->frag_list)) | ||
1244 | create_frag_buffer(&orig_node->frag_list); | ||
1245 | |||
1246 | tmp_frag_entry = | ||
1247 | search_frag_packet(&orig_node->frag_list, | ||
1248 | unicast_packet); | ||
1249 | |||
1250 | if (!tmp_frag_entry) { | ||
1251 | create_frag_entry(&orig_node->frag_list, skb); | ||
1252 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
1253 | return NET_RX_SUCCESS; | ||
1254 | } | ||
1255 | |||
1256 | skb = merge_frag_packet(&orig_node->frag_list, | ||
1257 | tmp_frag_entry, skb); | ||
1258 | spin_unlock_irqrestore(&orig_hash_lock, flags); | ||
1259 | if (!skb) | ||
1260 | return NET_RX_DROP; | ||
1261 | |||
1262 | interface_rx(skb, hdr_size); | ||
1263 | return NET_RX_SUCCESS; | ||
1264 | } | ||
1265 | |||
1266 | return route_unicast_packet(skb, recv_if, hdr_size); | ||
1267 | } | ||
1268 | |||
1194 | int recv_bcast_packet(struct sk_buff *skb) | 1269 | int recv_bcast_packet(struct sk_buff *skb) |
1195 | { | 1270 | { |
1196 | struct orig_node *orig_node; | 1271 | struct orig_node *orig_node; |
diff --git a/drivers/staging/batman-adv/routing.h b/drivers/staging/batman-adv/routing.h index 3eac64e3cf9..81c684f7a64 100644 --- a/drivers/staging/batman-adv/routing.h +++ b/drivers/staging/batman-adv/routing.h | |||
@@ -34,6 +34,7 @@ void update_routes(struct orig_node *orig_node, | |||
34 | unsigned char *hna_buff, int hna_buff_len); | 34 | unsigned char *hna_buff, int hna_buff_len); |
35 | int recv_icmp_packet(struct sk_buff *skb); | 35 | int recv_icmp_packet(struct sk_buff *skb); |
36 | int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); | 36 | int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if); |
37 | int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if); | ||
37 | int recv_bcast_packet(struct sk_buff *skb); | 38 | int recv_bcast_packet(struct sk_buff *skb); |
38 | int recv_vis_packet(struct sk_buff *skb); | 39 | int recv_vis_packet(struct sk_buff *skb); |
39 | int recv_bat_packet(struct sk_buff *skb, | 40 | int recv_bat_packet(struct sk_buff *skb, |
diff --git a/drivers/staging/batman-adv/soft-interface.c b/drivers/staging/batman-adv/soft-interface.c index 315fdeb38cf..d60b1a8ac7f 100644 --- a/drivers/staging/batman-adv/soft-interface.c +++ b/drivers/staging/batman-adv/soft-interface.c | |||
@@ -249,7 +249,9 @@ void interface_setup(struct net_device *dev) | |||
249 | #endif | 249 | #endif |
250 | dev->destructor = free_netdev; | 250 | dev->destructor = free_netdev; |
251 | 251 | ||
252 | dev->mtu = hardif_min_mtu(); | 252 | dev->mtu = ETH_DATA_LEN; /* can't call min_mtu, because the |
253 | * needed variables have not been | ||
254 | * initialized yet */ | ||
253 | dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the | 255 | dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the |
254 | * skbuff for our header */ | 256 | * skbuff for our header */ |
255 | 257 | ||
diff --git a/drivers/staging/batman-adv/types.h b/drivers/staging/batman-adv/types.h index 67bf4db32d5..ac165753e84 100644 --- a/drivers/staging/batman-adv/types.h +++ b/drivers/staging/batman-adv/types.h | |||
@@ -41,6 +41,7 @@ struct batman_if { | |||
41 | char addr_str[ETH_STR_LEN]; | 41 | char addr_str[ETH_STR_LEN]; |
42 | struct net_device *net_dev; | 42 | struct net_device *net_dev; |
43 | atomic_t seqno; | 43 | atomic_t seqno; |
44 | atomic_t frag_seqno; | ||
44 | unsigned char *packet_buff; | 45 | unsigned char *packet_buff; |
45 | int packet_len; | 46 | int packet_len; |
46 | struct kobject *hardif_obj; | 47 | struct kobject *hardif_obj; |
@@ -81,6 +82,8 @@ struct orig_node { | |||
81 | TYPE_OF_WORD bcast_bits[NUM_WORDS]; | 82 | TYPE_OF_WORD bcast_bits[NUM_WORDS]; |
82 | uint32_t last_bcast_seqno; | 83 | uint32_t last_bcast_seqno; |
83 | struct list_head neigh_list; | 84 | struct list_head neigh_list; |
85 | struct list_head frag_list; | ||
86 | unsigned long last_frag_packet; | ||
84 | struct { | 87 | struct { |
85 | uint8_t candidates; | 88 | uint8_t candidates; |
86 | struct neigh_node *selected; | 89 | struct neigh_node *selected; |
@@ -110,6 +113,7 @@ struct bat_priv { | |||
110 | struct net_device_stats stats; | 113 | struct net_device_stats stats; |
111 | atomic_t aggregation_enabled; | 114 | atomic_t aggregation_enabled; |
112 | atomic_t bonding_enabled; | 115 | atomic_t bonding_enabled; |
116 | atomic_t frag_enabled; | ||
113 | atomic_t vis_mode; | 117 | atomic_t vis_mode; |
114 | atomic_t orig_interval; | 118 | atomic_t orig_interval; |
115 | atomic_t log_level; | 119 | atomic_t log_level; |
@@ -183,4 +187,10 @@ struct debug_log { | |||
183 | wait_queue_head_t queue_wait; | 187 | wait_queue_head_t queue_wait; |
184 | }; | 188 | }; |
185 | 189 | ||
190 | struct frag_packet_list_entry { | ||
191 | struct list_head list; | ||
192 | uint16_t seqno; | ||
193 | struct sk_buff *skb; | ||
194 | }; | ||
195 | |||
186 | #endif /* _NET_BATMAN_ADV_TYPES_H_ */ | 196 | #endif /* _NET_BATMAN_ADV_TYPES_H_ */ |
diff --git a/drivers/staging/batman-adv/unicast.c b/drivers/staging/batman-adv/unicast.c index 27c4abb2530..153914e2951 100644 --- a/drivers/staging/batman-adv/unicast.c +++ b/drivers/staging/batman-adv/unicast.c | |||
@@ -28,6 +28,177 @@ | |||
28 | #include "routing.h" | 28 | #include "routing.h" |
29 | #include "hard-interface.h" | 29 | #include "hard-interface.h" |
30 | 30 | ||
31 | |||
32 | struct sk_buff *merge_frag_packet(struct list_head *head, | ||
33 | struct frag_packet_list_entry *tfp, | ||
34 | struct sk_buff *skb) | ||
35 | { | ||
36 | struct unicast_frag_packet *up = | ||
37 | (struct unicast_frag_packet *) skb->data; | ||
38 | struct sk_buff *tmp_skb; | ||
39 | |||
40 | /* set skb to the first part and tmp_skb to the second part */ | ||
41 | if (up->flags & UNI_FRAG_HEAD) { | ||
42 | tmp_skb = tfp->skb; | ||
43 | } else { | ||
44 | tmp_skb = skb; | ||
45 | skb = tfp->skb; | ||
46 | } | ||
47 | |||
48 | skb_pull(tmp_skb, sizeof(struct unicast_frag_packet)); | ||
49 | if (pskb_expand_head(skb, 0, tmp_skb->len, GFP_ATOMIC) < 0) { | ||
50 | /* free buffered skb, skb will be freed later */ | ||
51 | kfree_skb(tfp->skb); | ||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | /* move free entry to end */ | ||
56 | tfp->skb = NULL; | ||
57 | tfp->seqno = 0; | ||
58 | list_move_tail(&tfp->list, head); | ||
59 | |||
60 | memcpy(skb_put(skb, tmp_skb->len), tmp_skb->data, tmp_skb->len); | ||
61 | kfree_skb(tmp_skb); | ||
62 | return skb; | ||
63 | } | ||
64 | |||
65 | void create_frag_entry(struct list_head *head, struct sk_buff *skb) | ||
66 | { | ||
67 | struct frag_packet_list_entry *tfp; | ||
68 | struct unicast_frag_packet *up = | ||
69 | (struct unicast_frag_packet *) skb->data; | ||
70 | |||
71 | /* free and oldest packets stand at the end */ | ||
72 | tfp = list_entry((head)->prev, typeof(*tfp), list); | ||
73 | kfree_skb(tfp->skb); | ||
74 | |||
75 | tfp->seqno = ntohs(up->seqno); | ||
76 | tfp->skb = skb; | ||
77 | list_move(&tfp->list, head); | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | void create_frag_buffer(struct list_head *head) | ||
82 | { | ||
83 | int i; | ||
84 | struct frag_packet_list_entry *tfp; | ||
85 | |||
86 | for (i = 0; i < FRAG_BUFFER_SIZE; i++) { | ||
87 | tfp = kmalloc(sizeof(struct frag_packet_list_entry), | ||
88 | GFP_ATOMIC); | ||
89 | tfp->skb = NULL; | ||
90 | tfp->seqno = 0; | ||
91 | INIT_LIST_HEAD(&tfp->list); | ||
92 | list_add(&tfp->list, head); | ||
93 | } | ||
94 | |||
95 | return; | ||
96 | } | ||
97 | |||
98 | struct frag_packet_list_entry *search_frag_packet(struct list_head *head, | ||
99 | struct unicast_frag_packet *up) | ||
100 | { | ||
101 | struct frag_packet_list_entry *tfp; | ||
102 | struct unicast_frag_packet *tmp_up = NULL; | ||
103 | uint16_t search_seqno; | ||
104 | |||
105 | if (up->flags & UNI_FRAG_HEAD) | ||
106 | search_seqno = ntohs(up->seqno)+1; | ||
107 | else | ||
108 | search_seqno = ntohs(up->seqno)-1; | ||
109 | |||
110 | list_for_each_entry(tfp, head, list) { | ||
111 | |||
112 | if (!tfp->skb) | ||
113 | continue; | ||
114 | |||
115 | if (tfp->seqno == ntohs(up->seqno)) | ||
116 | goto mov_tail; | ||
117 | |||
118 | tmp_up = (struct unicast_frag_packet *) tfp->skb->data; | ||
119 | |||
120 | if (tfp->seqno == search_seqno) { | ||
121 | |||
122 | if ((tmp_up->flags & UNI_FRAG_HEAD) != | ||
123 | (up->flags & UNI_FRAG_HEAD)) | ||
124 | return tfp; | ||
125 | else | ||
126 | goto mov_tail; | ||
127 | } | ||
128 | } | ||
129 | return NULL; | ||
130 | |||
131 | mov_tail: | ||
132 | list_move_tail(&tfp->list, head); | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | void frag_list_free(struct list_head *head) | ||
137 | { | ||
138 | struct frag_packet_list_entry *pf, *tmp_pf; | ||
139 | |||
140 | if (!list_empty(head)) { | ||
141 | |||
142 | list_for_each_entry_safe(pf, tmp_pf, head, list) { | ||
143 | kfree_skb(pf->skb); | ||
144 | list_del(&pf->list); | ||
145 | kfree(pf); | ||
146 | } | ||
147 | } | ||
148 | return; | ||
149 | } | ||
150 | |||
151 | static int unicast_send_frag_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | ||
152 | struct batman_if *batman_if, uint8_t dstaddr[], | ||
153 | struct orig_node *orig_node) | ||
154 | { | ||
155 | struct unicast_frag_packet *ucast_frag1, *ucast_frag2; | ||
156 | int hdr_len = sizeof(struct unicast_frag_packet); | ||
157 | struct sk_buff *frag_skb; | ||
158 | int data_len = skb->len; | ||
159 | |||
160 | if (!bat_priv->primary_if) | ||
161 | goto dropped; | ||
162 | |||
163 | frag_skb = dev_alloc_skb(data_len - (data_len / 2) + hdr_len); | ||
164 | skb_split(skb, frag_skb, data_len / 2); | ||
165 | |||
166 | if (my_skb_push(frag_skb, hdr_len) < 0 || | ||
167 | my_skb_push(skb, hdr_len) < 0) | ||
168 | goto drop_frag; | ||
169 | |||
170 | ucast_frag1 = (struct unicast_frag_packet *)skb->data; | ||
171 | ucast_frag2 = (struct unicast_frag_packet *)frag_skb->data; | ||
172 | |||
173 | ucast_frag1->version = COMPAT_VERSION; | ||
174 | ucast_frag1->packet_type = BAT_UNICAST_FRAG; | ||
175 | ucast_frag1->ttl = TTL; | ||
176 | memcpy(ucast_frag1->orig, | ||
177 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
178 | memcpy(ucast_frag1->dest, orig_node->orig, ETH_ALEN); | ||
179 | |||
180 | memcpy(ucast_frag2, ucast_frag1, sizeof(struct unicast_frag_packet)); | ||
181 | |||
182 | ucast_frag1->flags |= UNI_FRAG_HEAD; | ||
183 | ucast_frag2->flags &= ~UNI_FRAG_HEAD; | ||
184 | |||
185 | ucast_frag1->seqno = htons((uint16_t)atomic_inc_return( | ||
186 | &batman_if->frag_seqno)); | ||
187 | |||
188 | ucast_frag2->seqno = htons((uint16_t)atomic_inc_return( | ||
189 | &batman_if->frag_seqno)); | ||
190 | |||
191 | send_skb_packet(skb, batman_if, dstaddr); | ||
192 | send_skb_packet(frag_skb, batman_if, dstaddr); | ||
193 | return 0; | ||
194 | |||
195 | drop_frag: | ||
196 | kfree_skb(frag_skb); | ||
197 | dropped: | ||
198 | kfree_skb(skb); | ||
199 | return 1; | ||
200 | } | ||
201 | |||
31 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | 202 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) |
32 | { | 203 | { |
33 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 204 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
@@ -35,6 +206,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
35 | struct orig_node *orig_node; | 206 | struct orig_node *orig_node; |
36 | struct batman_if *batman_if; | 207 | struct batman_if *batman_if; |
37 | struct neigh_node *router; | 208 | struct neigh_node *router; |
209 | int data_len = skb->len; | ||
38 | uint8_t dstaddr[6]; | 210 | uint8_t dstaddr[6]; |
39 | unsigned long flags; | 211 | unsigned long flags; |
40 | 212 | ||
@@ -63,6 +235,11 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
63 | if (batman_if->if_status != IF_ACTIVE) | 235 | if (batman_if->if_status != IF_ACTIVE) |
64 | goto dropped; | 236 | goto dropped; |
65 | 237 | ||
238 | if (atomic_read(&bat_priv->frag_enabled) && | ||
239 | data_len + sizeof(struct unicast_packet) > batman_if->net_dev->mtu) | ||
240 | return unicast_send_frag_skb(skb, bat_priv, batman_if, | ||
241 | dstaddr, orig_node); | ||
242 | |||
66 | if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) | 243 | if (my_skb_push(skb, sizeof(struct unicast_packet)) < 0) |
67 | goto dropped; | 244 | goto dropped; |
68 | 245 | ||
diff --git a/drivers/staging/batman-adv/unicast.h b/drivers/staging/batman-adv/unicast.h index dd00703103f..1d5cbeb6733 100644 --- a/drivers/staging/batman-adv/unicast.h +++ b/drivers/staging/batman-adv/unicast.h | |||
@@ -22,6 +22,18 @@ | |||
22 | #ifndef _NET_BATMAN_ADV_UNICAST_H_ | 22 | #ifndef _NET_BATMAN_ADV_UNICAST_H_ |
23 | #define _NET_BATMAN_ADV_UNICAST_H_ | 23 | #define _NET_BATMAN_ADV_UNICAST_H_ |
24 | 24 | ||
25 | #define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ | ||
26 | #define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ | ||
27 | |||
28 | struct sk_buff *merge_frag_packet(struct list_head *head, | ||
29 | struct frag_packet_list_entry *tfp, | ||
30 | struct sk_buff *skb); | ||
31 | |||
32 | void create_frag_entry(struct list_head *head, struct sk_buff *skb); | ||
33 | void create_frag_buffer(struct list_head *head); | ||
34 | struct frag_packet_list_entry *search_frag_packet(struct list_head *head, | ||
35 | struct unicast_frag_packet *up); | ||
36 | void frag_list_free(struct list_head *head); | ||
25 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv); | 37 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv); |
26 | 38 | ||
27 | #endif /* _NET_BATMAN_ADV_UNICAST_H_ */ | 39 | #endif /* _NET_BATMAN_ADV_UNICAST_H_ */ |