> --- a/include/net/mac80211.h > +++ b/include/net/mac80211.h > @@ -474,6 +474,7 @@ enum ieee80211_if_types { > IEEE80211_IF_TYPE_AP, > IEEE80211_IF_TYPE_STA, > IEEE80211_IF_TYPE_IBSS, > + IEEE80211_IF_TYPE_MESH, What happened to Dan's suggestion of calling this MESH_STA? And maybe in nl80211 as well? I might've missed something, was there a conclusion? Debugfs code looks good. > static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) > { > + int meshhdrlen; > + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); > + > + meshhdrlen = (sdata->type == IEEE80211_IF_TYPE_MESH) ? 5 : 0; > + > /* FIX: what would be proper limits for MTU? > * This interface uses 802.3 frames. */ > - if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6) { > + if (new_mtu < 256 || > + new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) { > printk(KERN_WARNING "%s: invalid MTU %d\n", > dev->name, new_mtu); > return -EINVAL; Are you sure this is appropriate? As the comment says, interface is 802.3 framed. Don't the 802.11 specifications usually keep the frame payload length and require the device to handle longer frames? > + atomic_t mesh_seqnum; Hmm. Do we really need an atomic_t here? > + case IEEE80211_IF_TYPE_MESH: > + if (!mesh_allocated) { > + /* Allocate all mesh structures when creating the first > + * mesh interface. > + */ > + mesh_pathtbl_init(); > + mesh_allocated = 1; > + } > + /* fall thru */ Will there be other structures to allocate? Maybe we should instead push the "already" check into the _init()? > + /* TODO: check for expired neighbors, paths and frames to non resolved > + * hw addresses > + */ Seems dangerous to actually run the code w/o this, no? > + mgmt->u.beacon.beacon_int = > + cpu_to_le16(local->hw.conf.beacon_int); Hmm. This is interesting. The beacon interval is a pure beacon configuration after my patches, but here we're using it without having userspace set up a beacon. What do we do in the IBSS case? > +static int o80211s_getmeshpath(struct sk_buff *skb, struct nlmsghdr *nlh, > + void *arg) > +{ > + return 0; > +} Uh huh. Why is this here? Should it be filled? > + read_lock(&mesh_paths_lock); When do we need the mesh paths? Should the structure use RCU maybe? > + if (sdata->type == IEEE80211_IF_TYPE_MESH) { > + int meshhdrlen = ieee80211_get_mesh_hdrlen( > + (struct ieee80211s_hdr *) skb->data); > + /* Copy mesh header on cb to be used if forwarded. > + * It will be used as mesh header template at > + * tx.c:ieee80211_subif_start_xmit() if interface > + * type is mesh and skb->pkt_type == PACKET_OTHERHOST > + */ > + memcpy(skb->cb, skb->data + hdrlen, meshhdrlen); > + hdrlen += meshhdrlen; Thanks for the explanation. This only happens when we dev_queue_xmit() it right away in the mesh forwarding code, right? > + /* Mesh forwarding */ > + if (sdata->type == IEEE80211_IF_TYPE_MESH) { > + u8 *mesh_ttl = &((struct ieee80211s_hdr *)skb->cb)->ttl; Oh it's used here too :) > @@ -230,6 +231,9 @@ ieee80211_tx_h_check_assoc(struct ieee80211_txrx_data *tx) > (tx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PROBE_REQ)) > return TXRX_DROP; > > + if (tx->sdata->type == IEEE80211_IF_TYPE_MESH) > + return TXRX_CONTINUE; Is this right or should there be some other "is forwarded frame" check to go with this? I'm not sure but it seems that frames we send via the netdev need to be still checked? Or not because they're just injected into the mesh? I think I'm confused. > + case IEEE80211_IF_TYPE_MESH: > + fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; > + /* RA TA DA SA */ > + if (is_multicast_ether_addr(skb->data)) > + memcpy(hdr.addr1, skb->data, ETH_ALEN); > + else if (ieee80211s_nh_lookup(skb->data, hdr.addr1)) { I think you should use RCU for the locking in the neighbour table. This code should (IIRC) be under rcu read-side lock already so the neighbour table reading would be lockless. Since updates are infrequent, RCU is a good tradeoff. > +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); Don't export this. > +int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, > + struct ieee80211_sub_if_data *sdata) > +{ > + /* TODO: create a per mesh interface atomic sequence counter */ > + int mesh_seqnum = atomic_inc_return(&sdata->u.sta.mesh_seqnum); Since you use new_mesh_header only from within the TX code which is serialised, you don't need atomic. Also, this *is* per-mesh interface (sdata), the TODO makes no sense. > +EXPORT_SYMBOL(ieee80211_new_mesh_header); Don't export this either. johannes
Attachment:
signature.asc
Description: This is a digitally signed message part