// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved. * Copyright (c) 2009 Intel Corporation. All rights reserved. * * Maintained at www.Open-FCoE.org */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/spinlock.h> #include <linux/timer.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/errno.h> #include <linux/bitops.h> #include <linux/slab.h> #include <net/rtnetlink.h> #include <scsi/fc/fc_els.h> #include <scsi/fc/fc_fs.h> #include <scsi/fc/fc_fip.h> #include <scsi/fc/fc_encaps.h> #include <scsi/fc/fc_fcoe.h> #include <scsi/fc/fc_fcp.h> #include <scsi/libfc.h> #include <scsi/libfcoe.h> #include "libfcoe.h" #define FCOE_CTLR_MIN_FKA … #define FCOE_CTLR_DEF_FKA … static void fcoe_ctlr_timeout(struct timer_list *); static void fcoe_ctlr_timer_work(struct work_struct *); static void fcoe_ctlr_recv_work(struct work_struct *); static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *); static void fcoe_ctlr_vn_start(struct fcoe_ctlr *); static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *); static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *); static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *, struct sk_buff *); static u8 fcoe_all_fcfs[ETH_ALEN] = …; static u8 fcoe_all_enode[ETH_ALEN] = …; static u8 fcoe_all_vn2vn[ETH_ALEN] = …; static u8 fcoe_all_p2p[ETH_ALEN] = …; static const char * const fcoe_ctlr_states[] = …; static const char *fcoe_ctlr_state(enum fip_state state) { … } /** * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state. * @fip: The FCoE controller * @state: The new state */ static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state) { … } /** * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid * @fcf: The FCF to check * * Return non-zero if FCF fcoe_size has been validated. */ static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf) { … } /** * fcoe_ctlr_fcf_usable() - Check if a FCF is usable * @fcf: The FCF to check * * Return non-zero if the FCF is usable. */ static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf) { … } /** * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses * @fip: The FCoE controller */ static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_init() - Initialize the FCoE Controller instance * @fip: The FCoE controller to initialize * @mode: FIP mode to set */ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_mode mode) { … } EXPORT_SYMBOL(…); /** * fcoe_sysfs_fcf_add() - Add a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} * @new: The newly discovered FCF * * Called with fip->ctlr_mutex held */ static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new) { … } /** * fcoe_sysfs_fcf_del() - Remove a fcoe_fcf{,_device} to a fcoe_ctlr{,_device} * @new: The FCF to be removed * * Called with fip->ctlr_mutex held */ static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new) { … } /** * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller * @fip: The FCoE controller whose FCFs are to be reset * * Called with &fcoe_ctlr lock held. */ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller * @fip: The FCoE controller to tear down * * This is called by FCoE drivers before freeing the &fcoe_ctlr. * * The receive handler will have been deleted before this to guarantee * that no more recv_work will be scheduled. * * The timer routine will simply return once we set FIP_ST_DISABLED. * This guarantees that no further timeouts or work will be scheduled. */ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip) { … } EXPORT_SYMBOL(…); /** * fcoe_ctlr_announce() - announce new FCF selection * @fip: The FCoE controller * * Also sets the destination MAC for FCoE and control packets * * Called with neither ctlr_mutex nor ctlr_lock held. */ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port * @fip: The FCoE controller to get the maximum FCoE size from * * Returns the maximum packet size including the FCoE header and trailer, * but not including any Ethernet or VLAN headers. */ static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_solicit() - Send a FIP solicitation * @fip: The FCoE controller to send the solicitation on * @fcf: The destination FCF (if NULL, a multicast solicitation is sent) */ static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf) { … } /** * fcoe_ctlr_link_up() - Start FCoE controller * @fip: The FCoE controller to start * * Called from the LLD when the network link is ready. */ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) { … } EXPORT_SYMBOL(…); /** * fcoe_ctlr_reset() - Reset a FCoE controller * @fip: The FCoE controller to reset */ static void fcoe_ctlr_reset(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_link_down() - Stop a FCoE controller * @fip: The FCoE controller to be stopped * * Returns non-zero if the link was up and now isn't. * * Called from the LLD when the network link is not ready. * There may be multiple calls while the link is down. */ int fcoe_ctlr_link_down(struct fcoe_ctlr *fip) { … } EXPORT_SYMBOL(…); /** * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF * @fip: The FCoE controller to send the FKA on * @lport: libfc fc_lport to send from * @ports: 0 for controller keep-alive, 1 for port keep-alive * @sa: The source MAC address * * A controller keep-alive is sent every fka_period (typically 8 seconds). * The source MAC is the native MAC address. * * A port keep-alive is sent every 90 seconds while logged in. * The source MAC is the assigned mapped source address. * The destination is the FCF's F-port. */ static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, struct fc_lport *lport, int ports, u8 *sa) { … } /** * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it * @fip: The FCoE controller for the ELS frame * @lport: The local port * @dtype: The FIP descriptor type for the frame * @skb: The FCoE ELS frame including FC header but no FCoE headers * @d_id: The destination port ID. * * Returns non-zero error code on failure. * * The caller must check that the length is a multiple of 4. * * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes). * Headroom includes the FIP encapsulation description, FIP header, and * Ethernet header. The tailroom is for the FIP MAC descriptor. */ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport, u8 dtype, struct sk_buff *skb, u32 d_id) { … } /** * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate. * @fip: FCoE controller. * @lport: libfc fc_lport to send from * @skb: FCoE ELS frame including FC header but no FCoE headers. * * Returns a non-zero error code if the frame should not be sent. * Returns zero if the caller should send the frame with FCoE encapsulation. * * The caller must check that the length is a multiple of 4. * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). * The the skb must also be an fc_frame. * * This is called from the lower-level driver with spinlocks held, * so we must not take a mutex here. */ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, struct sk_buff *skb) { … } EXPORT_SYMBOL(…); /** * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller * @fip: The FCoE controller to free FCFs on * * Called with lock held and preemption disabled. * * An FCF is considered old if we have missed two advertisements. * That is, there have been no valid advertisement from it for 2.5 * times its keep-alive period. * * In addition, determine the time when an FCF selection can occur. * * Also, increment the MissDiscAdvCount when no advertisement is received * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB). * * Returns the time in jiffies for the next call. */ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry * @fip: The FCoE controller receiving the advertisement * @skb: The received FIP advertisement frame * @fcf: The resulting FCF entry * * Returns zero on a valid parsed advertisement, * otherwise returns non zero value. */ static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip, struct sk_buff *skb, struct fcoe_fcf *fcf) { … } /** * fcoe_ctlr_recv_adv() - Handle an incoming advertisement * @fip: The FCoE controller receiving the advertisement * @skb: The received FIP packet */ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame * @fip: The FCoE controller which received the packet * @skb: The received FIP packet */ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_recv_clr_vlink() - Handle an incoming link reset frame * @fip: The FCoE controller that received the frame * @skb: The received FIP packet * * There may be multiple VN_Port descriptors. * The overall length has already been checked. */ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_recv() - Receive a FIP packet * @fip: The FCoE controller that received the packet * @skb: The received FIP packet * * This may be called from either NET_RX_SOFTIRQ or IRQ. */ void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } EXPORT_SYMBOL(…); /** * fcoe_ctlr_recv_handler() - Receive a FIP frame * @fip: The FCoE controller that received the frame * @skb: The received FIP frame * * Returns non-zero if the frame is dropped. */ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_select() - Select the best FCF (if possible) * @fip: The FCoE controller * * Returns the selected FCF, or NULL if none are usable. * * If there are conflicting advertisements, no FCF can be chosen. * * If there is already a selected FCF, this will choose a better one or * an equivalent one that hasn't already been sent a FLOGI. * * Called with lock held. */ static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF * @fip: The FCoE controller * * Returns non-zero error if it could not be sent. * * Called with ctlr_mutex and ctlr_lock held. * Caller must verify that fip->sel_fcf is not NULL. */ static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible * @fip: The FCoE controller * * Returns non-zero error code if there's no FLOGI request to retry or * no alternate FCF available. */ static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI. * @fip: The FCoE controller that timed out * * Done here because fcoe_ctlr_els_send() can't get mutex. * * Called with ctlr_mutex held. The caller must not hold ctlr_lock. */ static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_timeout() - FIP timeout handler * @t: Timer context use to obtain the controller reference */ static void fcoe_ctlr_timeout(struct timer_list *t) { … } /** * fcoe_ctlr_timer_work() - Worker thread function for timer work * @work: Handle to a FCoE controller * * Ages FCFs. Triggers FCF selection if possible. * Sends keep-alives and resets. */ static void fcoe_ctlr_timer_work(struct work_struct *work) { … } /** * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames * @recv_work: Handle to a FCoE controller */ static void fcoe_ctlr_recv_work(struct work_struct *recv_work) { … } /** * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response * @fip: The FCoE controller * @lport: The local port * @fp: The FC frame to snoop * * Snoop potential response to FLOGI or even incoming FLOGI. * * The caller has checked that we are waiting for login as indicated * by fip->flogi_oxid != FC_XID_UNKNOWN. * * The caller is responsible for freeing the frame. * Fill in the granted_mac address. * * Return non-zero if the frame should not be delivered to libfc. */ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport, struct fc_frame *fp) { … } EXPORT_SYMBOL(…); /** * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN * @mac: The MAC address to convert * @scheme: The scheme to use when converting * @port: The port indicator for converting * * Returns: u64 fc world wide name */ u64 fcoe_wwn_from_mac(unsigned char mac[ETH_ALEN], unsigned int scheme, unsigned int port) { … } EXPORT_SYMBOL_GPL(…); /** * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv * @rdata: libfc remote port */ static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata) { … } /** * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply. * @fip: The FCoE controller * @sub: sub-opcode for probe request, reply, or advertisement. * @dest: The destination Ethernet MAC address * @min_len: minimum size of the Ethernet payload to be sent */ static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip, enum fip_vn2vn_subcode sub, const u8 *dest, size_t min_len) { … } /** * fcoe_ctlr_vn_rport_callback - Event handler for rport events. * @lport: The lport which is receiving the event * @rdata: remote port private data * @event: The event that occurred * * Locking Note: The rport lock must not be held when calling this function. */ static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport, struct fc_rport_priv *rdata, enum fc_rport_event event) { … } static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = …; /** * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode * @lport: The local port * * Called with ctlr_mutex held. */ static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport) { … } /** * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode * @lport: The local port * * Called through the local port template for discovery. * Called without the ctlr_mutex held. */ static void fcoe_ctlr_disc_stop(struct fc_lport *lport) { … } /** * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode * @lport: The local port * * Called through the local port template for discovery. * Called without the ctlr_mutex held. */ static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport) { … } /** * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id * @fip: The FCoE controller * * Called with fcoe_ctlr lock held. */ static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_vn_start() - Start in VN2VN mode * @fip: The FCoE controller * * Called with fcoe_ctlr lock held. */ static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_vn_parse - parse probe request or response * @fip: The FCoE controller * @skb: incoming packet * @frport: parsed FCoE rport from the probe request * * Returns non-zero error number on error. * Does not consume the packet. */ static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip, struct sk_buff *skb, struct fcoe_rport *frport) { … } /** * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification. * @fip: The FCoE controller * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request. * @fip: The FCoE controller * @frport: parsed FCoE rport from the probe request * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, struct fcoe_rport *frport) { … } /** * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply. * @fip: The FCoE controller * @frport: parsed FCoE rport from the probe request * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip, struct fcoe_rport *frport) { … } /** * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply. * @fip: The FCoE controller * @new: newly-parsed FCoE rport as a template for new rdata * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fcoe_rport *new) { … } /** * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address * @fip: The FCoE controller * @port_id: The port_id of the remote VN_node * @mac: buffer which will hold the VN_NODE destination MAC address, if found. * * Returns non-zero error if no remote port found. */ static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac) { … } /** * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification * @fip: The FCoE controller * @new: newly-parsed FCoE rport as a template for new rdata * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip, struct fcoe_rport *new) { … } /** * fcoe_ctlr_vn_claim_resp() - handle received Claim Response * @fip: The FCoE controller that received the frame * @new: newly-parsed FCoE rport from the Claim Response * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip, struct fcoe_rport *new) { … } /** * fcoe_ctlr_vn_beacon() - handle received beacon. * @fip: The FCoE controller that received the frame * @new: newly-parsed FCoE rport from the Beacon * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip, struct fcoe_rport *new) { … } /** * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons * @fip: The FCoE controller * * Called with ctlr_mutex held. * Called only in state FIP_ST_VNMP_UP. * Returns the soonest time for next age-out or a time far in the future. */ static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_vn_recv() - Receive a FIP frame * @fip: The FCoE controller that received the frame * @skb: The received FIP frame * * Returns non-zero if the frame is dropped. * Always consumes the frame. */ static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_vlan_parse - parse vlan discovery request or response * @fip: The FCoE controller * @skb: incoming packet * @frport: parsed FCoE rport from the probe request * * Returns non-zero error number on error. * Does not consume the packet. */ static int fcoe_ctlr_vlan_parse(struct fcoe_ctlr *fip, struct sk_buff *skb, struct fcoe_rport *frport) { … } /** * fcoe_ctlr_vlan_send() - Send a FIP VLAN Notification * @fip: The FCoE controller * @sub: sub-opcode for vlan notification or vn2vn vlan notification * @dest: The destination Ethernet MAC address */ static void fcoe_ctlr_vlan_send(struct fcoe_ctlr *fip, enum fip_vlan_subcode sub, const u8 *dest) { … } /** * fcoe_ctlr_vlan_disc_reply() - send FIP VLAN Discovery Notification. * @fip: The FCoE controller * @frport: The newly-parsed FCoE rport from the Discovery Request * * Called with ctlr_mutex held. */ static void fcoe_ctlr_vlan_disc_reply(struct fcoe_ctlr *fip, struct fcoe_rport *frport) { … } /** * fcoe_ctlr_vlan_recv - vlan request receive handler for VN2VN mode. * @fip: The FCoE controller * @skb: The received FIP packet */ static int fcoe_ctlr_vlan_recv(struct fcoe_ctlr *fip, struct sk_buff *skb) { … } /** * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode. * @lport: The local port * @fp: The received frame * * This should never be called since we don't see RSCNs or other * fabric-generated ELSes. */ static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp) { … } /* * fcoe_ctlr_disc_start - start discovery for VN2VN mode. * * This sets a flag indicating that remote ports should be created * and started for the peers we discover. We use the disc_callback * pointer as that flag. Peers already discovered are created here. * * The lport lock is held during this call. The callback must be done * later, without holding either the lport or discovery locks. * The fcoe_ctlr lock may also be held during this call. */ static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *, enum fc_disc_event), struct fc_lport *lport) { … } /** * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state. * @fip: The FCoE controller * * Starts the FLOGI and PLOGI login process to each discovered rport for which * we've received at least one beacon. * Performs the discovery complete callback. */ static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode. * @fip: The FCoE controller */ static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip) { … } /** * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode * @lport: The local port to be (re)configured * @fip: The FCoE controller whose mode is changing * @fip_mode: The new fip mode * * Note that the we shouldn't be changing the libfc discovery settings * (fc_disc_config) while an lport is going through the libfc state * machine. The mode can only be changed when a fcoe_ctlr device is * disabled, so that should ensure that this routine is only called * when nothing is happening. */ static void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip, enum fip_mode fip_mode) { … } /** * fcoe_libfc_config() - Sets up libfc related properties for local port * @lport: The local port to configure libfc for * @fip: The FCoE controller in use by the local port * @tt: The libfc function template * @init_fcp: If non-zero, the FCP portion of libfc should be initialized * * Returns : 0 for success */ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip, const struct libfc_function_template *tt, int init_fcp) { … } EXPORT_SYMBOL_GPL(…); void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev) { … } EXPORT_SYMBOL(…); void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev) { … } EXPORT_SYMBOL(…);