From owner-svn-src-projects@FreeBSD.ORG Thu Apr 30 12:16:15 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EF0C9106567E; Thu, 30 Apr 2009 12:16:15 +0000 (UTC) (envelope-from rpaulo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DC4AD8FC14; Thu, 30 Apr 2009 12:16:15 +0000 (UTC) (envelope-from rpaulo@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n3UCGFrh011837; Thu, 30 Apr 2009 12:16:15 GMT (envelope-from rpaulo@svn.freebsd.org) Received: (from rpaulo@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n3UCGFSA011833; Thu, 30 Apr 2009 12:16:15 GMT (envelope-from rpaulo@svn.freebsd.org) Message-Id: <200904301216.n3UCGFSA011833@svn.freebsd.org> From: Rui Paulo Date: Thu, 30 Apr 2009 12:16:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191685 - projects/mesh11s/sys/net80211 X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 30 Apr 2009 12:16:16 -0000 Author: rpaulo Date: Thu Apr 30 12:16:15 2009 New Revision: 191685 URL: http://svn.freebsd.org/changeset/base/191685 Log: Initial implementation of Mesh Peering. This makes it possible to establish a mesh link with a Linux mesh node, but the code is still imature. Sponsored by: The FreeBSD Foundation Modified: projects/mesh11s/sys/net80211/ieee80211_ht.c projects/mesh11s/sys/net80211/ieee80211_mesh.c projects/mesh11s/sys/net80211/ieee80211_mesh.h projects/mesh11s/sys/net80211/ieee80211_node.h Modified: projects/mesh11s/sys/net80211/ieee80211_ht.c ============================================================================== --- projects/mesh11s/sys/net80211/ieee80211_ht.c Thu Apr 30 12:14:52 2009 (r191684) +++ projects/mesh11s/sys/net80211/ieee80211_ht.c Thu Apr 30 12:16:15 2009 (r191685) @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include /* define here, used throughout file */ #define MS(_v, _f) (((_v) & _f) >> _f##_S) @@ -2121,7 +2122,7 @@ ieee80211_send_action(struct ieee80211_n struct mbuf *m; uint8_t *frm; uint16_t baparamset; - int ret; + int ret, addsize; KASSERT(ni != NULL, ("null node")); @@ -2137,11 +2138,29 @@ ieee80211_send_action(struct ieee80211_n ieee80211_node_refcnt(ni)+1); ieee80211_ref_node(ni); + addsize = 0; + switch (category) { + case IEEE80211_ACTION_CAT_BA: + case IEEE80211_ACTION_CAT_HT: + addsize += sizeof(struct ieee80211_action_ba_addbaresponse); + break; + case IEEE80211_ACTION_CAT_MESHPEERING: + addsize += sizeof(uint16_t); /* capabilities */ + addsize += 2 + vap->iv_meshidlen; /* Mesh ID */ + addsize += sizeof(struct ieee80211_meshconf_ie); + /* On Open frames, the peer link ID is not sent */ + if (action == IEEE80211_ACTION_MESHPEERING_OPEN) + addsize += sizeof(struct ieee80211_meshpeer_ie) - 2; + else + addsize += sizeof(struct ieee80211_meshpeer_ie); + break; + } m = ieee80211_getmgtframe(&frm, ic->ic_headroom + sizeof(struct ieee80211_frame), sizeof(uint16_t) /* action+category */ /* XXX may action payload */ - + sizeof(struct ieee80211_action_ba_addbaresponse) + + addsize + ); if (m == NULL) senderr(ENOMEM, is_tx_nobuf); @@ -2210,6 +2229,43 @@ ieee80211_send_action(struct ieee80211_n goto badaction; } break; + case IEEE80211_ACTION_CAT_MESHPEERING: + + switch (action) { + case IEEE80211_ACTION_MESHPEERING_OPEN: + IEEE80211_NOTE(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni, + "send PEER OPEN action: lid %x", args[0]); + *frm++ = 0; /* capabilites */ + *frm++ = 0; + frm = ieee80211_add_meshid(frm, vap); + frm = ieee80211_add_meshconf(frm, vap); + *frm++ = IEEE80211_ELEMID_MESHPEER; + *frm++ = 3; /* len */ + *frm++ = IEEE80211_MESH_PEER_LINK_OPEN; /* subtype */ + ADDSHORT(frm, args[0]); /* local ID */ + break; + case IEEE80211_ACTION_MESHPEERING_CONFIRM: + IEEE80211_NOTE(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni, + "send PEER CONFIRM action: lid %x, pid %x", + args[0], args[1]); + *frm++ = 0; /* capabilites */ + *frm++ = 0; + *frm++ = 0; /* status code */ + *frm++ = 0; + *frm++ = 0; /* AID */ + *frm++ = 0; + frm = ieee80211_add_meshid(frm, vap); + frm = ieee80211_add_meshconf(frm, vap); + *frm++ = IEEE80211_ELEMID_MESHPEER; + *frm++ = 5; /* len */ + *frm++ = IEEE80211_MESH_PEER_LINK_CONFIRM; /* subtype */ + ADDSHORT(frm, args[0]); + ADDSHORT(frm, args[1]); + break; + } + break; default: badaction: IEEE80211_NOTE(vap, Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.c ============================================================================== --- projects/mesh11s/sys/net80211/ieee80211_mesh.c Thu Apr 30 12:14:52 2009 (r191684) +++ projects/mesh11s/sys/net80211/ieee80211_mesh.c Thu Apr 30 12:16:15 2009 (r191685) @@ -68,6 +68,7 @@ static int mesh_input(struct ieee80211_n uint32_t); static void mesh_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, int, int, uint32_t); +static void mesh_recv_action(struct ieee80211_node *, struct mbuf *); void ieee80211_mesh_attach(struct ieee80211com *ic) @@ -314,6 +315,7 @@ static void mesh_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0, int subtype, int rssi, int noise, uint32_t rstamp) { + static const uint8_t zerobssid[IEEE80211_ADDR_LEN]; struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; struct ieee80211_frame *wh; @@ -327,7 +329,6 @@ mesh_recv_mgmt(struct ieee80211_node *ni case IEEE80211_FC0_SUBTYPE_BEACON: { struct ieee80211_scanparams scan; - /* * We process beacon/probe response * frames to discover neighbors. @@ -363,6 +364,42 @@ mesh_recv_mgmt(struct ieee80211_node *ni return; } + /* The rest of this code assumes we setup and running */ + if (vap->iv_state != IEEE80211_S_RUN) + return; + /* + * Ignore non-mesh STAs and STAs for other mesh networks. + */ + if (scan.meshid && + memcmp(scan.meshid+2, vap->iv_meshid, vap->iv_meshidlen) != 0) { + IEEE80211_NOTE(vap, IEEE80211_MSG_MESH, ni, + "beacon not for our mesh (%s)", scan.meshid+2); + return; + } + + /* + * More validation: make sure we are talking to a Mesh node. + */ + if ((scan.capinfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) == 0 && + !IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_macaddr) && + IEEE80211_ADDR_EQ(wh->i_addr3, zerobssid)) { + /* + * Create a new entry in the neighbor table. + */ + ni = ieee80211_add_neighbor(vap, wh, &scan); + } else { + /* + * Record tsf for potential resync. + */ + memcpy(ni->ni_tstamp.data, scan.tstamp, + sizeof(ni->ni_tstamp)); + } + if (ni != NULL) { + IEEE80211_RSSI_LPF(ni->ni_avgrssi, rssi); + ni->ni_noise = noise; + ni->ni_rstamp = rstamp; + } + /* * If it's a beacon for our mesh and we haven't already * peered with this node, send him a mgmt frame with @@ -443,11 +480,15 @@ mesh_recv_mgmt(struct ieee80211_node *ni break; } case IEEE80211_FC0_SUBTYPE_ACTION: - if (vap->iv_state == IEEE80211_S_RUN) { - if (ieee80211_parse_action(ni, m0) == 0) - ic->ic_recv_action(ni, frm, efrm); - } else + if (vap->iv_state != IEEE80211_S_RUN) { vap->iv_stats.is_rx_mgtdiscard++; + break; + } + /* XXX parse_action is a bit useless now */ + if (ieee80211_parse_action(ni, m0) == 0) { + mesh_recv_action(ni, m0); + ic->ic_recv_action(ni, frm, efrm); + } break; case IEEE80211_FC0_SUBTYPE_AUTH: case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: @@ -467,6 +508,97 @@ mesh_recv_mgmt(struct ieee80211_node *ni break; } } +static void +mesh_recv_action(struct ieee80211_node *ni, struct mbuf *m0) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_action *ia; + struct ieee80211_frame *wh; + struct ieee80211_meshid_ie *meshid; + struct ieee80211_meshconf_ie *meshconf; + struct ieee80211_meshpeer_ie *meshpeer; + uint8_t *frm, *efrm; + uint16_t args[4]; + + wh = mtod(m0, struct ieee80211_frame *); + ia = (struct ieee80211_action *) &wh[1]; + frm = (uint8_t *)&wh[1]; + frm += sizeof(ia); + efrm = mtod(m0, uint8_t *) + m0->m_len; + + /* XXX explain frame format */ + meshid = NULL; + meshpeer = NULL; + meshconf = NULL; + while (efrm - frm > 1) { + IEEE80211_VERIFY_LENGTH(efrm - frm, frm[1] + 2, return); + switch (*frm) { + case IEEE80211_ELEMID_MESHID: + meshid = (struct ieee80211_meshid_ie *) frm; + break; + case IEEE80211_ELEMID_MESHCONF: + meshconf = (struct ieee80211_meshconf_ie *) frm; + break; + case IEEE80211_ELEMID_MESHPEER: + meshpeer = (struct ieee80211_meshpeer_ie *) frm; + break; + } + frm += frm[1] + 2; + } + /* + * Check if we agree on Mesh ID and Configuration. + * XXX: TBD + */ + if (!meshid || !meshconf || !meshpeer) { + IEEE80211_DISCARD(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, + wh, NULL, "%s", "action frame not for our mesh"); + vap->iv_stats.is_rx_mgtdiscard++; + return; + } + switch (ia->ia_category) { + case IEEE80211_ACTION_CAT_MESHPEERING: + switch (ia->ia_action) { + case IEEE80211_ACTION_MESHPEERING_OPEN: + IEEE80211_NOTE(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni, + "%s", "recv peering open"); + ni->ni_peerstate = IEEE80211_NODE_MESH_OPENRCV; + ni->ni_llid = meshpeer->peer_llinkid; + ni->ni_plid = 0xf4ef; + args[0] = ni->ni_plid; + ieee80211_send_action(ni, + IEEE80211_ACTION_CAT_MESHPEERING, + IEEE80211_ACTION_MESHPEERING_OPEN, args); + break; + case IEEE80211_ACTION_MESHPEERING_CONFIRM: + IEEE80211_NOTE(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, ni, + "%s", "recv peering confirm"); + if (ni->ni_peerstate != IEEE80211_NODE_MESH_OPNSENT && + ni->ni_peerstate != IEEE80211_NODE_MESH_OPENRCV) { + IEEE80211_DISCARD(vap, + IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, + wh, NULL, "received confirm in invalid " + "state %d", ni->ni_peerstate); + vap->iv_stats.is_rx_mgtdiscard++; + return; + } + ni->ni_peerstate = IEEE80211_NODE_MESH_CONFIRMRECV; + args[0] = 0xf4ef; + args[1] = ni->ni_llid; + ieee80211_send_action(ni, + IEEE80211_ACTION_CAT_MESHPEERING, + IEEE80211_ACTION_MESHPEERING_CONFIRM, args); + } + break; + default: + IEEE80211_DISCARD(vap, IEEE80211_MSG_ACTION | IEEE80211_MSG_MESH, + wh, NULL, "%s", "not handled"); + vap->iv_stats.is_rx_mgtdiscard++; + } +} + /* * Parse a MESH ID ie on station join. */ Modified: projects/mesh11s/sys/net80211/ieee80211_mesh.h ============================================================================== --- projects/mesh11s/sys/net80211/ieee80211_mesh.h Thu Apr 30 12:14:52 2009 (r191684) +++ projects/mesh11s/sys/net80211/ieee80211_mesh.h Thu Apr 30 12:16:15 2009 (r191685) @@ -250,6 +250,20 @@ struct ieee80211_meshpuc_ie { uint8_t puc_daddr[IEEE80211_ADDR_LEN]; } __packed; +/* + * 802.11s Action Frames + */ +#define IEEE80211_ACTION_CAT_MESHPEERING 30 /* XXX Linux */ +#define IEEE80211_ACTION_CAT_MESHLINK 13 +#define IEEE80211_ACTION_CAT_PATHSEL 14 +#define IEEE80211_ACTION_CAT_INTERWORK 15 +#define IEEE80211_ACTION_CAT_RESOURCE 16 +#define IEEE80211_ACTION_CAT_PROXY 17 + +#define IEEE80211_ACTION_MESHPEERING_OPEN 0 +#define IEEE80211_ACTION_MESHPEERING_CONFIRM 1 +#define IEEE80211_ACTION_MESHPEERING_CLOSE 2 + void ieee80211_mesh_attach(struct ieee80211com *); void ieee80211_mesh_detach(struct ieee80211com *); void ieee80211_parse_meshid(struct ieee80211_node *, const uint8_t *); Modified: projects/mesh11s/sys/net80211/ieee80211_node.h ============================================================================== --- projects/mesh11s/sys/net80211/ieee80211_node.h Thu Apr 30 12:14:52 2009 (r191684) +++ projects/mesh11s/sys/net80211/ieee80211_node.h Thu Apr 30 12:16:15 2009 (r191685) @@ -36,7 +36,7 @@ * Each ieee80211com instance has a single timer that fires every * IEEE80211_INACT_WAIT seconds to handle "inactivity processing". * This is used to do node inactivity processing when operating - * as an AP or in adhoc mode. For inactivity processing each node + * as an AP, adhoc or mesh mode. For inactivity processing each node * has a timeout set in it's ni_inact field that is decremented * on each timeout and the node is reclaimed when the counter goes * to zero. We use different inactivity timeout values depending @@ -175,6 +175,17 @@ struct ieee80211_node { uint8_t ni_dtim_period; /* DTIM period */ uint8_t ni_dtim_count; /* DTIM count for last bcn */ + /* mesh */ +#define IEEE80211_NODE_MESH_IDLE 0 +#define IEEE80211_NODE_MESH_OPNSENT 1 /* Peer Open Frame Received */ +#define IEEE80211_NODE_MESH_OPENRCV 2 /* Peer Open Frame Sent */ +#define IEEE80211_NODE_MESH_CONFIRMRECV 3 /* Peer Confirm Frame Recvived */ +#define IEEE80211_NODE_MESH_ESTABLISHED 4 /* Peer Link Established */ +#define IEEE80211_NODE_MESH_HOLDING 5 /* Peer Link Closing */ + int8_t ni_peerstate; /* Mesh Peering state */ + uint16_t ni_llid; /* local link ID */ + uint16_t ni_plid; /* peer link ID */ + /* 11n state */ uint16_t ni_htcap; /* HT capabilities */ uint8_t ni_htparam; /* HT params */