/* * llc_sap.c - driver routines for SAP component. * * Copyright (c) 1997 by Procom Technology, Inc. * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * * This program can be redistributed or modified under the terms of the * GNU General Public License as published by the Free Software Foundation. * This program is distributed without any warranty or implied warranty * of merchantability or fitness for a particular purpose. * * See the GNU General Public License for more details.
*/
staticint llc_mac_header_len(unsignedshort devtype)
{ switch (devtype) { case ARPHRD_ETHER: case ARPHRD_LOOPBACK: returnsizeof(struct ethhdr);
} return 0;
}
/** * llc_alloc_frame - allocates sk_buff for frame * @sk: socket to allocate frame to * @dev: network device this skb will be sent over * @type: pdu type to allocate * @data_size: data size to allocate * * Allocates an sk_buff for frame and initializes sk_buff fields. * Returns allocated skb or %NULL when out of memory.
*/ struct sk_buff *llc_alloc_frame(struct sock *sk, struct net_device *dev,
u8 type, u32 data_size)
{ int hlen = type == LLC_PDU_TYPE_U ? 3 : 4; struct sk_buff *skb;
/* save primitive for use by the user. */
addr = llc_ui_skb_cb(skb);
memset(addr, 0, sizeof(*addr));
addr->sllc_family = sk->sk_family;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = prim == LLC_TEST_PRIM;
addr->sllc_xid = prim == LLC_XID_PRIM;
addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
llc_pdu_decode_sa(skb, addr->sllc_mac);
llc_pdu_decode_ssap(skb, &addr->sllc_sap);
}
/** * llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu. * @sap: pointer to SAP * @skb: received pdu
*/ void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
{ struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
switch (LLC_U_PDU_RSP(pdu)) { case LLC_1_PDU_CMD_TEST:
ev->prim = LLC_TEST_PRIM; break; case LLC_1_PDU_CMD_XID:
ev->prim = LLC_XID_PRIM; break; case LLC_1_PDU_CMD_UI:
ev->prim = LLC_DATAUNIT_PRIM; break;
}
ev->ind_cfm_flag = LLC_IND;
}
/** * llc_find_sap_trans - finds transition for event * @sap: pointer to SAP * @skb: happened event * * This function finds transition that matches with happened event. * Returns the pointer to found transition on success or %NULL for * failure.
*/ staticconststruct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, struct sk_buff *skb)
{ int i = 0; conststruct llc_sap_state_trans *rc = NULL; conststruct llc_sap_state_trans **next_trans; struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1]; /* * Search thru events for this state until list exhausted or until * its obvious the event is not valid for the current state
*/ for (next_trans = curr_state->transitions; next_trans[i]->ev; i++) if (!next_trans[i]->ev(sap, skb)) {
rc = next_trans[i]; /* got event match; return it */ break;
} return rc;
}
/** * llc_exec_sap_trans_actions - execute actions related to event * @sap: pointer to SAP * @trans: pointer to transition that it's actions must be performed * @skb: happened event. * * This function executes actions that is related to happened event. * Returns 0 for success and 1 for failure of at least one action.
*/ staticint llc_exec_sap_trans_actions(struct llc_sap *sap, conststruct llc_sap_state_trans *trans, struct sk_buff *skb)
{ int rc = 0; const llc_sap_action_t *next_action = trans->ev_actions;
for (; next_action && *next_action; next_action++) if ((*next_action)(sap, skb))
rc = 1; return rc;
}
/** * llc_sap_next_state - finds transition, execs actions & change SAP state * @sap: pointer to SAP * @skb: happened event * * This function finds transition that matches with happened event, then * executes related actions and finally changes state of SAP. It returns * 0 on success and 1 for failure.
*/ staticint llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb)
{ conststruct llc_sap_state_trans *trans; int rc = 1;
if (sap->state > LLC_NR_SAP_STATES) goto out;
trans = llc_find_sap_trans(sap, skb); if (!trans) goto out; /* * Got the state to which we next transition; perform the actions * associated with this transition before actually transitioning to the * next state
*/
rc = llc_exec_sap_trans_actions(sap, trans, skb); if (rc) goto out; /* * Transition SAP to next state if all actions execute successfully
*/
sap->state = trans->next_state;
out: return rc;
}
/** * llc_sap_state_process - sends event to SAP state machine * @sap: sap to use * @skb: pointer to occurred event * * After executing actions of the event, upper layer will be indicated * if needed(on receiving an UI frame). sk can be null for the * datalink_proto case. * * This function always consumes a reference to the skb.
*/ staticvoid llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
{ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/* queue skb to the user. */ if (sock_queue_rcv_skb(skb->sk, skb) == 0) return;
}
kfree_skb(skb);
}
/** * llc_build_and_send_test_pkt - TEST interface for upper layers. * @sap: sap to use * @skb: packet to send * @dmac: destination mac address * @dsap: destination sap * * This function is called when upper layer wants to send a TEST pdu. * Returns 0 for success, 1 otherwise.
*/ void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb, u8 *dmac, u8 dsap)
{ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/** * llc_build_and_send_xid_pkt - XID interface for upper layers * @sap: sap to use * @skb: packet to send * @dmac: destination mac address * @dsap: destination sap * * This function is called when upper layer wants to send a XID pdu. * Returns 0 for success, 1 otherwise.
*/ void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/** * llc_sap_rcv - sends received pdus to the sap state machine * @sap: current sap component structure. * @skb: received frame. * @sk: socket to associate to frame * * Sends received pdus to the sap state machine.
*/ staticvoid llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb, struct sock *sk)
{ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/** * llc_lookup_dgram - Finds dgram socket for the local sap/mac * @sap: SAP * @laddr: address of local LLC (MAC + SAP) * @net: netns to look up a socket in * * Search socket list of the SAP and finds connection using the local * mac, and local sap. Returns pointer for socket found, %NULL otherwise.
*/ staticstruct sock *llc_lookup_dgram(struct llc_sap *sap, conststruct llc_addr *laddr, conststruct net *net)
{ struct sock *rc; struct hlist_nulls_node *node; int slot = llc_sk_laddr_hashfn(sap, laddr); struct hlist_nulls_head *laddr_hb = &sap->sk_laddr_hash[slot];
rcu_read_lock_bh();
again:
sk_nulls_for_each_rcu(rc, node, laddr_hb) { if (llc_dgram_match(sap, laddr, rc, net)) { /* Extra checks required by SLAB_TYPESAFE_BY_RCU */ if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt))) goto again; if (unlikely(llc_sk(rc)->sap != sap ||
!llc_dgram_match(sap, laddr, rc, net))) {
sock_put(rc); continue;
} goto found;
}
}
rc = NULL; /* * if the nulls value we got at the end of this lookup is * not the expected one, we must restart lookup. * We probably met an item that was moved to another chain.
*/ if (unlikely(get_nulls_value(node) != slot)) goto again;
found:
rcu_read_unlock_bh(); return rc;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.