linux/net/mac80211/tx.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2002-2005, Instant802 Networks, Inc.
 * Copyright 2005-2006, Devicescape Software, Inc.
 * Copyright 2006-2007	Jiri Benc <[email protected]>
 * Copyright 2007	Johannes Berg <[email protected]>
 * Copyright 2013-2014  Intel Mobile Communications GmbH
 * Copyright (C) 2018-2024 Intel Corporation
 *
 * Transmit and frame generation functions.
 */

#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/skbuff.h>
#include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include <linux/bitmap.h>
#include <linux/rcupdate.h>
#include <linux/export.h>
#include <net/net_namespace.h>
#include <net/ieee80211_radiotap.h>
#include <net/cfg80211.h>
#include <net/mac80211.h>
#include <net/codel.h>
#include <net/codel_impl.h>
#include <asm/unaligned.h>
#include <net/fq_impl.h>
#include <net/gso.h>

#include "ieee80211_i.h"
#include "driver-ops.h"
#include "led.h"
#include "mesh.h"
#include "wep.h"
#include "wpa.h"
#include "wme.h"
#include "rate.h"

/* misc utils */

static __le16 ieee80211_duration(struct ieee80211_tx_data *tx,
				 struct sk_buff *skb, int group_addr,
				 int next_frag_len)
{}

/* tx handlers */
static ieee80211_tx_result debug_noinline
ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
{}

/* This function is called whenever the AP is about to exceed the maximum limit
 * of buffered frames for power saving STAs. This situation should not really
 * happen often during normal operation, so dropping the oldest buffered packet
 * from each queue should be OK to make some room for new frames. */
static void purge_old_ps_buffers(struct ieee80211_local *local)
{}

static ieee80211_tx_result
ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
{}

static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
			     struct sk_buff *skb)
{}

static ieee80211_tx_result
ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
{}

static struct ieee80211_key *
ieee80211_select_link_key(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
{}

static __le16 ieee80211_tx_next_seq(struct sta_info *sta, int tid)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
{}

static int ieee80211_fragment(struct ieee80211_tx_data *tx,
			      struct sk_buff *skb, int hdrlen,
			      int frag_threshold)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
{}

static ieee80211_tx_result debug_noinline
ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
{}

/* actual transmit path */

static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx,
				  struct sk_buff *skb,
				  struct ieee80211_tx_info *info,
				  struct tid_ampdu_tx *tid_tx,
				  int tid)
{}

void ieee80211_aggr_check(struct ieee80211_sub_if_data *sdata,
			  struct sta_info *sta, struct sk_buff *skb)
{}

/*
 * initialises @tx
 * pass %NULL for the station if unknown, a valid pointer if known
 * or an ERR_PTR() if the station is known not to exist
 */
static ieee80211_tx_result
ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata,
		     struct ieee80211_tx_data *tx,
		     struct sta_info *sta, struct sk_buff *skb)
{}

static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
					  struct ieee80211_vif *vif,
					  struct sta_info *sta,
					  struct sk_buff *skb)
{}

static void ieee80211_set_skb_enqueue_time(struct sk_buff *skb)
{}

static u32 codel_skb_len_func(const struct sk_buff *skb)
{}

static codel_time_t codel_skb_time_func(const struct sk_buff *skb)
{}

static struct sk_buff *codel_dequeue_func(struct codel_vars *cvars,
					  void *ctx)
{}

static void codel_drop_func(struct sk_buff *skb,
			    void *ctx)
{}

static struct sk_buff *fq_tin_dequeue_func(struct fq *fq,
					   struct fq_tin *tin,
					   struct fq_flow *flow)
{}

static void fq_skb_free_func(struct fq *fq,
			     struct fq_tin *tin,
			     struct fq_flow *flow,
			     struct sk_buff *skb)
{}

static void ieee80211_txq_enqueue(struct ieee80211_local *local,
				  struct txq_info *txqi,
				  struct sk_buff *skb)
{}

static bool fq_vlan_filter_func(struct fq *fq, struct fq_tin *tin,
				struct fq_flow *flow, struct sk_buff *skb,
				void *data)
{}

void ieee80211_txq_remove_vlan(struct ieee80211_local *local,
			       struct ieee80211_sub_if_data *sdata)
{}

void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
			struct sta_info *sta,
			struct txq_info *txqi, int tid)
{}

void ieee80211_txq_purge(struct ieee80211_local *local,
			 struct txq_info *txqi)
{}

void ieee80211_txq_set_params(struct ieee80211_local *local)
{}

int ieee80211_txq_setup_flows(struct ieee80211_local *local)
{}

void ieee80211_txq_teardown_flows(struct ieee80211_local *local)
{}

static bool ieee80211_queue_skb(struct ieee80211_local *local,
				struct ieee80211_sub_if_data *sdata,
				struct sta_info *sta,
				struct sk_buff *skb)
{}

static bool ieee80211_tx_frags(struct ieee80211_local *local,
			       struct ieee80211_vif *vif,
			       struct sta_info *sta,
			       struct sk_buff_head *skbs,
			       bool txpending)
{}

/*
 * Returns false if the frame couldn't be transmitted but was queued instead.
 */
static bool __ieee80211_tx(struct ieee80211_local *local,
			   struct sk_buff_head *skbs, struct sta_info *sta,
			   bool txpending)
{}

/*
 * Invoke TX handlers, return 0 on success and non-zero if the
 * frame was dropped or queued.
 *
 * The handlers are split into an early and late part. The latter is everything
 * that can be sensitive to reordering, and will be deferred to after packets
 * are dequeued from the intermediate queues (when they are enabled).
 */
static int invoke_tx_handlers_early(struct ieee80211_tx_data *tx)
{}

/*
 * Late handlers can be called while the sta lock is held. Handlers that can
 * cause packets to be generated will cause deadlock!
 */
static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
{}

static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
{}

bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif, struct sk_buff *skb,
			      int band, struct ieee80211_sta **sta)
{}
EXPORT_SYMBOL();

/*
 * Returns false if the frame couldn't be transmitted but was queued instead.
 */
static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
			 struct sta_info *sta, struct sk_buff *skb,
			 bool txpending)
{}

/* device xmit handlers */

enum ieee80211_encrypt {};

static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
				struct sk_buff *skb,
				int head_need,
				enum ieee80211_encrypt encrypt)
{}

void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
		    struct sta_info *sta, struct sk_buff *skb)
{}

static bool ieee80211_validate_radiotap_len(struct sk_buff *skb)
{}

bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
				 struct net_device *dev)
{}

netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
					 struct net_device *dev)
{}

static inline bool ieee80211_is_tdls_setup(struct sk_buff *skb)
{}

int ieee80211_lookup_ra_sta(struct ieee80211_sub_if_data *sdata,
			    struct sk_buff *skb,
			    struct sta_info **sta_out)
{}

static u16 ieee80211_store_ack_skb(struct ieee80211_local *local,
				   struct sk_buff *skb,
				   u32 *info_flags,
				   u64 *cookie)
{}

/**
 * ieee80211_build_hdr - build 802.11 header in the given frame
 * @sdata: virtual interface to build the header for
 * @skb: the skb to build the header in
 * @info_flags: skb flags to set
 * @sta: the station pointer
 * @ctrl_flags: info control flags to set
 * @cookie: cookie pointer to fill (if not %NULL)
 *
 * This function takes the skb with 802.3 header and reformats the header to
 * the appropriate IEEE 802.11 header based on which interface the packet is
 * being transmitted on.
 *
 * Note that this function also takes care of the TX status request and
 * potential unsharing of the SKB - this needs to be interleaved with the
 * header building.
 *
 * The function requires the read-side RCU lock held
 *
 * Returns: the (possibly reallocated) skb or an ERR_PTR() code
 */
static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb, u32 info_flags,
					   struct sta_info *sta, u32 ctrl_flags,
					   u64 *cookie)
{}

/*
 * fast-xmit overview
 *
 * The core idea of this fast-xmit is to remove per-packet checks by checking
 * them out of band. ieee80211_check_fast_xmit() implements the out-of-band
 * checks that are needed to get the sta->fast_tx pointer assigned, after which
 * much less work can be done per packet. For example, fragmentation must be
 * disabled or the fast_tx pointer will not be set. All the conditions are seen
 * in the code here.
 *
 * Once assigned, the fast_tx data structure also caches the per-packet 802.11
 * header and other data to aid packet processing in ieee80211_xmit_fast().
 *
 * The most difficult part of this is that when any of these assumptions
 * change, an external trigger (i.e. a call to ieee80211_clear_fast_xmit(),
 * ieee80211_check_fast_xmit() or friends) is required to reset the data,
 * since the per-packet code no longer checks the conditions. This is reflected
 * by the calls to these functions throughout the rest of the code, and must be
 * maintained if any of the TX path checks change.
 */

void ieee80211_check_fast_xmit(struct sta_info *sta)
{}

void ieee80211_check_fast_xmit_all(struct ieee80211_local *local)
{}

void ieee80211_check_fast_xmit_iface(struct ieee80211_sub_if_data *sdata)
{}

void ieee80211_clear_fast_xmit(struct sta_info *sta)
{}

static bool ieee80211_amsdu_realloc_pad(struct ieee80211_local *local,
					struct sk_buff *skb, int headroom)
{}

static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
					 struct ieee80211_fast_tx *fast_tx,
					 struct sk_buff *skb)
{}

static bool ieee80211_amsdu_aggregate(struct ieee80211_sub_if_data *sdata,
				      struct sta_info *sta,
				      struct ieee80211_fast_tx *fast_tx,
				      struct sk_buff *skb,
				      const u8 *da, const u8 *sa)
{}

/*
 * Can be called while the sta lock is held. Anything that can cause packets to
 * be generated will cause deadlock!
 */
static ieee80211_tx_result
ieee80211_xmit_fast_finish(struct ieee80211_sub_if_data *sdata,
			   struct sta_info *sta, u8 pn_offs,
			   struct ieee80211_key *key,
			   struct ieee80211_tx_data *tx)
{}

static netdev_features_t
ieee80211_sdata_netdev_features(struct ieee80211_sub_if_data *sdata)
{}

static struct sk_buff *
ieee80211_tx_skb_fixup(struct sk_buff *skb, netdev_features_t features)
{}

void __ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
			   struct sta_info *sta,
			   struct ieee80211_fast_tx *fast_tx,
			   struct sk_buff *skb, bool ampdu,
			   const u8 *da, const u8 *sa)
{}

static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
				struct sta_info *sta,
				struct ieee80211_fast_tx *fast_tx,
				struct sk_buff *skb)
{}

struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
				     struct ieee80211_txq *txq)
{}
EXPORT_SYMBOL();

static inline s32 ieee80211_sta_deficit(struct sta_info *sta, u8 ac)
{}

static void
ieee80211_txq_set_active(struct txq_info *txqi)
{}

static bool
ieee80211_txq_keep_active(struct txq_info *txqi)
{}

struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)
{}
EXPORT_SYMBOL();

void __ieee80211_schedule_txq(struct ieee80211_hw *hw,
			      struct ieee80211_txq *txq,
			      bool force)
{}
EXPORT_SYMBOL();

DEFINE_STATIC_KEY_FALSE(aql_disable);

bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
				 struct ieee80211_txq *txq)
{}
EXPORT_SYMBOL();

static bool
ieee80211_txq_schedule_airtime_check(struct ieee80211_local *local, u8 ac)
{}

bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,
				struct ieee80211_txq *txq)
{}
EXPORT_SYMBOL();

void ieee80211_txq_schedule_start(struct ieee80211_hw *hw, u8 ac)
{}
EXPORT_SYMBOL();

void __ieee80211_subif_start_xmit(struct sk_buff *skb,
				  struct net_device *dev,
				  u32 info_flags,
				  u32 ctrl_flags,
				  u64 *cookie)
{}

static int ieee80211_change_da(struct sk_buff *skb, struct sta_info *sta)
{}

static bool ieee80211_multicast_to_unicast(struct sk_buff *skb,
					   struct net_device *dev)
{}

static void
ieee80211_convert_to_unicast(struct sk_buff *skb, struct net_device *dev,
			     struct sk_buff_head *queue)
{}

static void ieee80211_mlo_multicast_tx_one(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb, u32 ctrl_flags,
					   unsigned int link_id)
{}

static void ieee80211_mlo_multicast_tx(struct net_device *dev,
				       struct sk_buff *skb)
{}

/**
 * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
 * @skb: packet to be sent
 * @dev: incoming interface
 *
 * On failure skb will be freed.
 *
 * Returns: the netdev TX status (but really only %NETDEV_TX_OK)
 */
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
				       struct net_device *dev)
{}



static bool __ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
				struct sk_buff *skb, struct sta_info *sta,
				bool txpending)
{}

static bool ieee80211_tx_8023(struct ieee80211_sub_if_data *sdata,
			      struct sk_buff *skb, struct sta_info *sta,
			      bool txpending)
{}

static void ieee80211_8023_xmit(struct ieee80211_sub_if_data *sdata,
				struct net_device *dev, struct sta_info *sta,
				struct ieee80211_key *key, struct sk_buff *skb)
{}

netdev_tx_t ieee80211_subif_start_xmit_8023(struct sk_buff *skb,
					    struct net_device *dev)
{}

struct sk_buff *
ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
			      struct sk_buff *skb, u32 info_flags)
{}

/*
 * ieee80211_clear_tx_pending may not be called in a context where
 * it is possible that it packets could come in again.
 */
void ieee80211_clear_tx_pending(struct ieee80211_local *local)
{}

/*
 * Returns false if the frame couldn't be transmitted but was queued instead,
 * which in this case means re-queued -- take as an indication to stop sending
 * more pending frames.
 */
static bool ieee80211_tx_pending_skb(struct ieee80211_local *local,
				     struct sk_buff *skb)
{}

/*
 * Transmit all pending packets. Called from tasklet.
 */
void ieee80211_tx_pending(struct tasklet_struct *t)
{}

/* functions for drivers to get certain frames */

static void __ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
				       struct ieee80211_link_data *link,
				       struct ps_data *ps, struct sk_buff *skb,
				       bool is_template)
{}

static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
				    struct ieee80211_link_data *link,
				    struct ps_data *ps, struct sk_buff *skb,
				    bool is_template)
{}

static void ieee80211_set_beacon_cntdwn(struct ieee80211_sub_if_data *sdata,
					struct beacon_data *beacon,
					struct ieee80211_link_data *link)
{}

static u8 __ieee80211_beacon_update_cntdwn(struct beacon_data *beacon)
{}

u8 ieee80211_beacon_update_cntdwn(struct ieee80211_vif *vif, unsigned int link_id)
{}
EXPORT_SYMBOL();

void ieee80211_beacon_set_cntdwn(struct ieee80211_vif *vif, u8 counter)
{}
EXPORT_SYMBOL();

bool ieee80211_beacon_cntdwn_is_complete(struct ieee80211_vif *vif,
					 unsigned int link_id)
{}
EXPORT_SYMBOL();

static int ieee80211_beacon_protect(struct sk_buff *skb,
				    struct ieee80211_local *local,
				    struct ieee80211_sub_if_data *sdata,
				    struct ieee80211_link_data *link)
{}

static void
ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
			    struct ieee80211_vif *vif,
			    struct ieee80211_link_data *link,
			    struct ieee80211_mutable_offsets *offs,
			    struct beacon_data *beacon,
			    struct sk_buff *skb,
			    struct ieee80211_chanctx_conf *chanctx_conf,
			    u16 csa_off_base)
{}

static void
ieee80211_beacon_add_mbssid(struct sk_buff *skb, struct beacon_data *beacon,
			    u8 i)
{}

static struct sk_buff *
ieee80211_beacon_get_ap(struct ieee80211_hw *hw,
			struct ieee80211_vif *vif,
			struct ieee80211_link_data *link,
			struct ieee80211_mutable_offsets *offs,
			bool is_template,
			struct beacon_data *beacon,
			struct ieee80211_chanctx_conf *chanctx_conf,
			u8 ema_index)
{}

static struct ieee80211_ema_beacons *
ieee80211_beacon_get_ap_ema_list(struct ieee80211_hw *hw,
				 struct ieee80211_vif *vif,
				 struct ieee80211_link_data *link,
				 struct ieee80211_mutable_offsets *offs,
				 bool is_template, struct beacon_data *beacon,
				 struct ieee80211_chanctx_conf *chanctx_conf)
{}

#define IEEE80211_INCLUDE_ALL_MBSSID_ELEMS

static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw *hw,
		       struct ieee80211_vif *vif,
		       struct ieee80211_mutable_offsets *offs,
		       bool is_template,
		       unsigned int link_id,
		       int ema_index,
		       struct ieee80211_ema_beacons **ema_beacons)
{}

struct sk_buff *
ieee80211_beacon_get_template(struct ieee80211_hw *hw,
			      struct ieee80211_vif *vif,
			      struct ieee80211_mutable_offsets *offs,
			      unsigned int link_id)
{}
EXPORT_SYMBOL();

struct sk_buff *
ieee80211_beacon_get_template_ema_index(struct ieee80211_hw *hw,
					struct ieee80211_vif *vif,
					struct ieee80211_mutable_offsets *offs,
					unsigned int link_id, u8 ema_index)
{}
EXPORT_SYMBOL();

void ieee80211_beacon_free_ema_list(struct ieee80211_ema_beacons *ema_beacons)
{}
EXPORT_SYMBOL();

struct ieee80211_ema_beacons *
ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif,
				       unsigned int link_id)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
					 struct ieee80211_vif *vif,
					 u16 *tim_offset, u16 *tim_length,
					 unsigned int link_id)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
					struct ieee80211_vif *vif)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_get_fils_discovery_tmpl(struct ieee80211_hw *hw,
						  struct ieee80211_vif *vif)
{}
EXPORT_SYMBOL();

struct sk_buff *
ieee80211_get_unsol_bcast_probe_resp_tmpl(struct ieee80211_hw *hw,
					  struct ieee80211_vif *vif)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_pspoll_get(struct ieee80211_hw *hw,
				     struct ieee80211_vif *vif)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
				       struct ieee80211_vif *vif,
				       int link_id, bool qos_ok)
{}
EXPORT_SYMBOL();

struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
				       const u8 *src_addr,
				       const u8 *ssid, size_t ssid_len,
				       size_t tailroom)
{}
EXPORT_SYMBOL();

void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
		       const void *frame, size_t frame_len,
		       const struct ieee80211_tx_info *frame_txctl,
		       struct ieee80211_rts *rts)
{}
EXPORT_SYMBOL();

void ieee80211_ctstoself_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
			     const void *frame, size_t frame_len,
			     const struct ieee80211_tx_info *frame_txctl,
			     struct ieee80211_cts *cts)
{}
EXPORT_SYMBOL();

struct sk_buff *
ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
			  struct ieee80211_vif *vif)
{}
EXPORT_SYMBOL();

int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
{}
EXPORT_SYMBOL();

void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
{}
EXPORT_SYMBOL();

void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
				 struct sk_buff *skb, int tid, int link_id,
				 enum nl80211_band band)
{}

void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata,
			  struct sk_buff *skb, int tid, int link_id)
{}

int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
			      const u8 *buf, size_t len,
			      const u8 *dest, __be16 proto, bool unencrypted,
			      int link_id, u64 *cookie)
{}

int ieee80211_probe_mesh_link(struct wiphy *wiphy, struct net_device *dev,
			      const u8 *buf, size_t len)
{}