// SPDX-License-Identifier: GPL-2.0-only
/*
 * OCB mode implementation
 *
 * Copyright: (c) 2014 Czech Technical University in Prague
 *            (c) 2014 Volkswagen Group Research
 * Copyright (C) 2022 Intel Corporation
 * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
 * Funded by: Volkswagen Group Research
 */

#include <linux/delay.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/rtnetlink.h>
#include <net/mac80211.h>
#include <asm/unaligned.h>

#include "ieee80211_i.h"
#include "driver-ops.h"
#include "rate.h"

#define IEEE80211_OCB_HOUSEKEEPING_INTERVAL		(60 * HZ)
#define IEEE80211_OCB_PEER_INACTIVITY_LIMIT		(240 * HZ)
#define IEEE80211_OCB_MAX_STA_ENTRIES			128

/**
 * enum ocb_deferred_task_flags - mac80211 OCB deferred tasks
 * @OCB_WORK_HOUSEKEEPING: run the periodic OCB housekeeping tasks
 *
 * These flags are used in @wrkq_flags field of &struct ieee80211_if_ocb
 */
enum ocb_deferred_task_flags {
	OCB_WORK_HOUSEKEEPING,
};

void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
			     const u8 *bssid, const u8 *addr,
			     u32 supp_rates)
{
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_supported_band *sband;
	enum nl80211_bss_scan_width scan_width;
	struct sta_info *sta;
	int band;

	/* XXX: Consider removing the least recently used entry and
	 *      allow new one to be added.
	 */
	if (local->num_sta >= IEEE80211_OCB_MAX_STA_ENTRIES) {
		net_info_ratelimited("%s: No room for a new OCB STA entry %pM\n",
				     sdata->name, addr);
		return;
	}

	ocb_dbg(sdata, "Adding new OCB station %pM\n", addr);

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
	if (WARN_ON_ONCE(!chanctx_conf)) {
		rcu_read_unlock();
		return;
	}
	band = chanctx_conf->def.chan->band;
	scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
	rcu_read_unlock();

	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
	if (!sta)
		return;

	/* Add only mandatory rates for now */
	sband = local->hw.wiphy->bands[band];
	sta->sta.deflink.supp_rates[band] =
		ieee80211_mandatory_rates(sband, scan_width);

	spin_lock(&ifocb->incomplete_lock);
	list_add(&sta->list, &ifocb->incomplete_stations);
	spin_unlock(&ifocb->incomplete_lock);
	ieee80211_queue_work(&local->hw, &sdata->work);
}

static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
	__acquires(RCU)
{
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	u8 addr[ETH_ALEN];

	memcpy(addr, sta->sta.addr, ETH_ALEN);

	ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
		addr, sdata->name);

	sta_info_move_state(sta, IEEE80211_STA_AUTH);
	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
	sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);

	rate_control_rate_init(sta);

	/* If it fails, maybe we raced another insertion? */
	if (sta_info_insert_rcu(sta))
		return sta_info_get(sdata, addr);
	return sta;
}

static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;

	ocb_dbg(sdata, "Running ocb housekeeping\n");

	ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);

	mod_timer(&ifocb->housekeeping_timer,
		  round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
}

void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
	struct sta_info *sta;

	if (ifocb->joined != true)
		return;

	sdata_lock(sdata);

	spin_lock_bh(&ifocb->incomplete_lock);
	while (!list_empty(&ifocb->incomplete_stations)) {
		sta = list_first_entry(&ifocb->incomplete_stations,
				       struct sta_info, list);
		list_del(&sta->list);
		spin_unlock_bh(&ifocb->incomplete_lock);

		ieee80211_ocb_finish_sta(sta);
		rcu_read_unlock();
		spin_lock_bh(&ifocb->incomplete_lock);
	}
	spin_unlock_bh(&ifocb->incomplete_lock);

	if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
		ieee80211_ocb_housekeeping(sdata);

	sdata_unlock(sdata);
}

static void ieee80211_ocb_housekeeping_timer(struct timer_list *t)
{
	struct ieee80211_sub_if_data *sdata =
		from_timer(sdata, t, u.ocb.housekeeping_timer);
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;

	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);

	ieee80211_queue_work(&local->hw, &sdata->work);
}

void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;

	timer_setup(&ifocb->housekeeping_timer,
		    ieee80211_ocb_housekeeping_timer, 0);
	INIT_LIST_HEAD(&ifocb->incomplete_stations);
	spin_lock_init(&ifocb->incomplete_lock);
}

int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
		       struct ocb_setup *setup)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
	u32 changed = BSS_CHANGED_OCB | BSS_CHANGED_BSSID;
	int err;

	if (ifocb->joined == true)
		return -EINVAL;

	sdata->deflink.operating_11g_mode = true;
	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
	sdata->deflink.needed_rx_chains = sdata->local->rx_chains;

	mutex_lock(&sdata->local->mtx);
	err = ieee80211_link_use_channel(&sdata->deflink, &setup->chandef,
					 IEEE80211_CHANCTX_SHARED);
	mutex_unlock(&sdata->local->mtx);
	if (err)
		return err;

	ieee80211_bss_info_change_notify(sdata, changed);

	ifocb->joined = true;

	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
	ieee80211_queue_work(&local->hw, &sdata->work);

	netif_carrier_on(sdata->dev);
	return 0;
}

int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
{
	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;

	ifocb->joined = false;
	sta_info_flush(sdata);

	spin_lock_bh(&ifocb->incomplete_lock);
	while (!list_empty(&ifocb->incomplete_stations)) {
		sta = list_first_entry(&ifocb->incomplete_stations,
				       struct sta_info, list);
		list_del(&sta->list);
		spin_unlock_bh(&ifocb->incomplete_lock);

		sta_info_free(local, sta);
		spin_lock_bh(&ifocb->incomplete_lock);
	}
	spin_unlock_bh(&ifocb->incomplete_lock);

	netif_carrier_off(sdata->dev);
	clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);

	mutex_lock(&sdata->local->mtx);
	ieee80211_link_release_channel(&sdata->deflink);
	mutex_unlock(&sdata->local->mtx);

	skb_queue_purge(&sdata->skb_queue);

	del_timer_sync(&sdata->u.ocb.housekeeping_timer);
	/* If the timer fired while we waited for it, it will have
	 * requeued the work. Now the work will be running again
	 * but will not rearm the timer again because it checks
	 * whether we are connected to the network or not -- at this
	 * point we shouldn't be anymore.
	 */

	return 0;
}
