/* * * sgc_server.c * Description: * PP Sessions Group Counter over MRPC server driver * * * GPL LICENSE SUMMARY * * Copyright(c) 2016-2019 Intel Corporation. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. * The full GNU General Public License is included in this distribution * in the file called LICENSE.GPL. * * Contact Information: * Intel Corporation * 2200 Mission College Blvd. * Santa Clara, CA 97052 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef CONFIG_AVM_RDKB_MODEM_OSS_11_IFTABLE_DOT1DTPPORT_FIX /* Intel style is with defines ... */ #define IFNAME_MGMTIF_0 "mgmtif0" #define IFNAMES_LANPORTS "eth0", "eth1", "eth2", "eth3" #define VLAN_HDR_SIZE 4 /* * switch on/off pr_debug for this module * * echo -n 'file sgc_server.c +p' > /sys/kernel/debug/dynamic_debug/control * echo -n 'file sgc_server.c -p' > /sys/kernel/debug/dynamic_debug/control */ #endif /* driver private database */ struct SgcServerPrivate { struct platform_device *pdev; /* platform device */ struct mrpc_server *mrpc; /* mrpc server handle */ struct sgc_funcs *callbacks; }; enum { SGC_ALLOC_GROUP_COUNTER_ID_PROC = 0, SGC_RELEASE_GROUP_COUNTER_ID_PROC, SGC_DEL_GROUP_COUNTER_SESSIONS_PROC, SGC_GET_GROUP_COUNTER_AMOUNT_PROC, SGC_GET_IF_COUNTERS_PROC, SGC_GET_TP_PORT_COUNTERS_PROC, SGC_GET_SF_COUNTERS_PROC, SGC_PRINT_TPPORT_COUNTERS_PROC, SGC_PRINT_IF_COUNTERS_PROC, SGC_PRINT_GROUP_COUNTERS_PROC, SGC_RESTART_GROUP_COUNTER_ID_PROC, SGC_RELEASE_GROUP_COUNTERS_TABLE_PROC, SGC_DEL_GROUP_COUNTERS_SESSIONS_TABLE_PROC, }; static struct SgcServerPrivate *sgcServerDb; /**************************************************************************/ /*! \fn void mrpc_sgc_server_unregister(void) ************************************************************************** * \brief unregister sgc callbacks * \param[in] None * \param[out] None * \return 0 for success, error code otherwise. **************************************************************************/ void mrpc_sgc_server_unregister(void) { WARN_ON(!sgcServerDb); WARN_ON(!sgcServerDb->callbacks); kfree(sgcServerDb->callbacks); sgcServerDb->callbacks = NULL; pr_info("callback functions unregistered\n"); } EXPORT_SYMBOL(mrpc_sgc_server_unregister); /**************************************************************************/ /*! \fn int mrpc_sgc_server_register(struct sgc_funcs *callbacks) ************************************************************************** * \brief register sgc callbacks * \param[in] sgc_funcs - Pointer to callback functions structure/ * \param[out] None * \return 0 for success, error code otherwise. **************************************************************************/ int mrpc_sgc_server_register(struct sgc_funcs *callbacks) { WARN_ON(!sgcServerDb); WARN_ON(!callbacks); WARN_ON(sgcServerDb->callbacks); sgcServerDb->callbacks = kzalloc(sizeof(*callbacks), GFP_KERNEL); if (!sgcServerDb->callbacks) { pr_err("Failed to allocate memory\n"); return -ENOMEM; } memcpy(sgcServerDb->callbacks, callbacks, sizeof(*callbacks)); pr_info("callback functions registered\n"); return 0; } EXPORT_SYMBOL(mrpc_sgc_server_register); /**************************************************************************/ /*! \fn static int mrpc_sgc_AllocGroupCounter * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Allocate group counter. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_AllocGroupCounter (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret; unsigned short allocGroupCounterId; unsigned int tmpGroupCounterId; unsigned int *repGroupCounterId = (unsigned int *)rep; WARN_ON(!sgcServerDb->callbacks); ret = sgcServerDb->callbacks->PPSGC_Db_AllocGroupCounterId (&allocGroupCounterId); tmpGroupCounterId = allocGroupCounterId; tmpGroupCounterId = htonl(tmpGroupCounterId); *repGroupCounterId = tmpGroupCounterId; return ret; } /**************************************************************************/ /*! \fn static int mrpc_sgc_ReleaseGroupCounter * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Release group counter. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_ReleaseGroupCounter (void *arg, ssize_t arglen, void *rep, ssize_t replen) { unsigned int *argGroupCounterId = (unsigned int *)arg; unsigned int tmpGroupCounterId; unsigned short relGroupCounterId; tmpGroupCounterId = *argGroupCounterId; tmpGroupCounterId = ntohl(tmpGroupCounterId); relGroupCounterId = tmpGroupCounterId; WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_ReleaseGroupCounterId (relGroupCounterId); } /**************************************************************************/ /*! \fn static int mrpc_sgc_DelGroupCounterSessions * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Delete group counter sessions. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_DelGroupCounterSessions (void *arg, ssize_t arglen, void *rep, ssize_t replen) { unsigned int *argGroupCounterId = (unsigned int *)arg; unsigned int tmpGroupCounterId; unsigned short delGroupCounterId; tmpGroupCounterId = *argGroupCounterId; tmpGroupCounterId = ntohl(tmpGroupCounterId); delGroupCounterId = tmpGroupCounterId; WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_DeleteGroupCounterSessions (delGroupCounterId); } /**************************************************************************/ /*! \fn static int mrpc_sgc_GetGroupCounterAmount * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get group counter sessions traffic amount. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetGroupCounterAmount (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret; unsigned int *argGroupCounterId = (unsigned int *)arg; unsigned int tmpGroupCounterId; struct PpsgcPpCounters *repPpCounters = (struct PpsgcPpCounters *)rep; struct PpsgcGroupCounters groupCounters; tmpGroupCounterId = *argGroupCounterId; tmpGroupCounterId = ntohl(tmpGroupCounterId); groupCounters.groupCounterId = tmpGroupCounterId; WARN_ON(!sgcServerDb->callbacks); ret = sgcServerDb->callbacks-> PPSGC_Db_GetGroupCounterAmount(&groupCounters); repPpCounters->totalBytesFwd = cpu_to_be64(groupCounters.ppCounters.totalBytesFwd); repPpCounters->totalPktsFwd = cpu_to_be64(groupCounters.ppCounters.totalPktsFwd); repPpCounters->multicastPktsFwd = cpu_to_be64(groupCounters.ppCounters.multicastPktsFwd); repPpCounters->unicastPktsFwd = cpu_to_be64(groupCounters.ppCounters.unicastPktsFwd); return ret; } #ifndef CONFIG_AVM_RDKB_MODEM_OSS_11_IFTABLE_DOT1DTPPORT_FIX /**************************************************************************/ /*! \fn static int mrpc_sgc_GetIfCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get IF counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetIfCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret; struct PpsgcIfCounters ppsgcIfCounters = {0}; struct PpsgcIfCounters *argPpsgcIfCounters = (struct PpsgcIfCounters *)arg; struct PpsgcIfCounters *repPpsgcIfCounter = (struct PpsgcIfCounters *)rep; WARN_ON(!sgcServerDb->callbacks); strncpy(ppsgcIfCounters.ifName, argPpsgcIfCounters->ifName, sizeof(ppsgcIfCounters.ifName)-1); ppsgcIfCounters.includeQosDrops = argPpsgcIfCounters->includeQosDrops; ret = sgcServerDb->callbacks->PPSGC_Db_GetIfCounters(&ppsgcIfCounters); repPpsgcIfCounter->ifCounters.rx_byte = cpu_to_be64(ppsgcIfCounters.ifCounters.rx_byte); repPpsgcIfCounter->ifCounters.rx_unicast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.rx_unicast_pkt); repPpsgcIfCounter->ifCounters.rx_broadcast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.rx_broadcast_pkt); repPpsgcIfCounter->ifCounters.rx_multicast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.rx_multicast_pkt); repPpsgcIfCounter->ifCounters.rx_discard_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.rx_discard_pkt); repPpsgcIfCounter->ifCounters.tx_byte = cpu_to_be64(ppsgcIfCounters.ifCounters.tx_byte); repPpsgcIfCounter->ifCounters.tx_unicast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.tx_unicast_pkt); repPpsgcIfCounter->ifCounters.tx_broadcast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.tx_broadcast_pkt); repPpsgcIfCounter->ifCounters.tx_multicast_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.tx_multicast_pkt); repPpsgcIfCounter->ifCounters.tx_discard_pkt = cpu_to_be64(ppsgcIfCounters.ifCounters.tx_discard_pkt); return ret; } /**************************************************************************/ /*! \fn static int mrpc_sgc_GetTpPortCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get TP counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetTpPortCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret; struct PpsgcTpPortCounters ppsgcTpPortCounters = {0}; struct PpsgcTpPortCounters *argPpsgcTpPortCounters = (struct PpsgcTpPortCounters *)arg; struct PpsgcTpPortCounters *repPpsgcTpPortCounters = (struct PpsgcTpPortCounters *)rep; WARN_ON(!sgcServerDb->callbacks); strncpy(ppsgcTpPortCounters.ifName, argPpsgcTpPortCounters->ifName, sizeof(ppsgcTpPortCounters.ifName)-1); ret = sgcServerDb->callbacks-> PPSGC_Db_GetTpPortCounters(&ppsgcTpPortCounters); repPpsgcTpPortCounters->tpCounters.rx_byte = cpu_to_be64(ppsgcTpPortCounters.tpCounters.rx_byte); repPpsgcTpPortCounters->tpCounters.rx_unicast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.rx_unicast_pkt); repPpsgcTpPortCounters->tpCounters.rx_broadcast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.rx_broadcast_pkt); repPpsgcTpPortCounters->tpCounters.rx_multicast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.rx_multicast_pkt); repPpsgcTpPortCounters->tpCounters.rx_discard_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.rx_discard_pkt); repPpsgcTpPortCounters->tpCounters.tx_byte = cpu_to_be64(ppsgcTpPortCounters.tpCounters.tx_byte); repPpsgcTpPortCounters->tpCounters.tx_unicast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.tx_unicast_pkt); repPpsgcTpPortCounters->tpCounters.tx_broadcast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.tx_broadcast_pkt); repPpsgcTpPortCounters->tpCounters.tx_multicast_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.tx_multicast_pkt); repPpsgcTpPortCounters->tpCounters.tx_discard_pkt = cpu_to_be64(ppsgcTpPortCounters.tpCounters.tx_discard_pkt); return ret; } #else // CONFIG_AVM_RDKB_MODEM_OSS_11_IFTABLE_DOT1DTPPORT_FIX /******** helper for mrpc_sgc_GetIfCounters *******************************/ static int AddIfCounters(const char *ifName, struct PpsgcIfCounters *Counters) { int ret; struct PpsgcIfCounters ppsgcIfCounters = {0}; strncpy(ppsgcIfCounters.ifName, ifName, sizeof(ppsgcIfCounters.ifName)-1); ppsgcIfCounters.includeQosDrops = Counters->includeQosDrops; ret = sgcServerDb->callbacks->PPSGC_Db_GetIfCounters(&ppsgcIfCounters); #define ADD_VALUE(member) Counters->ifCounters.member += ppsgcIfCounters.ifCounters.member ADD_VALUE(rx_byte); ADD_VALUE(rx_unicast_pkt); ADD_VALUE(rx_broadcast_pkt); ADD_VALUE(rx_multicast_pkt); ADD_VALUE(rx_discard_pkt); ADD_VALUE(tx_byte); ADD_VALUE(tx_unicast_pkt); ADD_VALUE(tx_broadcast_pkt); ADD_VALUE(tx_multicast_pkt); ADD_VALUE(tx_discard_pkt); #undef ADD_VALUE return ret; } static void IfCounters2be(struct PpsgcIfCounters *Counters) { #define VALUE_TOBE(member) Counters->ifCounters.member = cpu_to_be64(Counters->ifCounters.member) VALUE_TOBE(rx_byte); VALUE_TOBE(rx_unicast_pkt); VALUE_TOBE(rx_broadcast_pkt); VALUE_TOBE(rx_multicast_pkt); VALUE_TOBE(rx_discard_pkt); VALUE_TOBE(tx_byte); VALUE_TOBE(tx_unicast_pkt); VALUE_TOBE(tx_broadcast_pkt); VALUE_TOBE(tx_multicast_pkt); VALUE_TOBE(tx_discard_pkt); #undef VALUE_TOBE } /**************************************************************************/ /*! \fn static int mrpc_sgc_GetIfCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get IF counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetIfCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret = PPSGC_RC_SUCCESS; struct PpsgcIfCounters *argPpsgcIfCounters = (struct PpsgcIfCounters *)arg; struct PpsgcIfCounters *repPpsgcIfCounter = (struct PpsgcIfCounters *)rep; WARN_ON(!sgcServerDb->callbacks); memset(repPpsgcIfCounter, 0, sizeof(struct PpsgcIfCounters)); repPpsgcIfCounter->includeQosDrops = argPpsgcIfCounters->includeQosDrops; if (strncmp(argPpsgcIfCounters->ifName, IFNAME_MGMTIF_0, strlen(IFNAME_MGMTIF_0)) != 0) { ret = AddIfCounters(argPpsgcIfCounters->ifName, repPpsgcIfCounter); pr_debug("%s(%s)=%d\n", __func__, argPpsgcIfCounters->ifName, ret); } else { char *ifaces[] = { IFNAMES_LANPORTS, 0 }; Uint64 rx_packets; int i, tmp; for (i = 0; ifaces[i]; i++) { tmp = AddIfCounters(ifaces[i], repPpsgcIfCounter); if (tmp) ret = tmp; } /* * Because the lan ports are vlan devices, we need to reduce * the rx_byte by the 4 byte per packet (vlan header). * * 2018-11-28, calle */ rx_packets = repPpsgcIfCounter->ifCounters.rx_unicast_pkt + repPpsgcIfCounter->ifCounters.rx_multicast_pkt + repPpsgcIfCounter->ifCounters.rx_broadcast_pkt; repPpsgcIfCounter->ifCounters.rx_byte -= rx_packets * VLAN_HDR_SIZE; pr_debug("%s(%s)=%d (lan ports)\n", __func__, argPpsgcIfCounters->ifName, ret); } #define PRINTVAL64(member) pr_debug("%-16s %16llu\n", #member, repPpsgcIfCounter->ifCounters.member) PRINTVAL64(rx_byte); PRINTVAL64(rx_unicast_pkt); PRINTVAL64(rx_broadcast_pkt); PRINTVAL64(rx_multicast_pkt); PRINTVAL64(rx_discard_pkt); PRINTVAL64(tx_byte); PRINTVAL64(tx_unicast_pkt); PRINTVAL64(tx_broadcast_pkt); PRINTVAL64(tx_multicast_pkt); PRINTVAL64(tx_discard_pkt); #undef PRINTVAL64 IfCounters2be(repPpsgcIfCounter); return ret; } /******** helper for mrpc_sgc_GetTpPortCounters ***************************/ static int AddTpPortCounters(const char *ifName, struct PpsgcTpPortCounters *Counters) { int ret; struct PpsgcTpPortCounters ppsgcTpPortCounters = {0}; strncpy(ppsgcTpPortCounters.ifName, ifName, sizeof(ppsgcTpPortCounters.ifName)-1); ret = sgcServerDb->callbacks-> PPSGC_Db_GetTpPortCounters(&ppsgcTpPortCounters); #define ADD_VALUE(member) Counters->tpCounters.member += ppsgcTpPortCounters.tpCounters.member ADD_VALUE(rx_byte); ADD_VALUE(rx_unicast_pkt); ADD_VALUE(rx_broadcast_pkt); ADD_VALUE(rx_multicast_pkt); ADD_VALUE(rx_discard_pkt); ADD_VALUE(tx_byte); ADD_VALUE(tx_unicast_pkt); ADD_VALUE(tx_broadcast_pkt); ADD_VALUE(tx_multicast_pkt); ADD_VALUE(tx_discard_pkt); #undef ADD_VALUE return ret; } static void TpPortCounters2be(struct PpsgcTpPortCounters *Counters) { #define VALUE_TOBE(member) Counters->tpCounters.member = cpu_to_be64(Counters->tpCounters.member) VALUE_TOBE(rx_byte); VALUE_TOBE(rx_unicast_pkt); VALUE_TOBE(rx_broadcast_pkt); VALUE_TOBE(rx_multicast_pkt); VALUE_TOBE(rx_discard_pkt); VALUE_TOBE(tx_byte); VALUE_TOBE(tx_unicast_pkt); VALUE_TOBE(tx_broadcast_pkt); VALUE_TOBE(tx_multicast_pkt); VALUE_TOBE(tx_discard_pkt); #undef VALUE_TOBE } /**************************************************************************/ /*! \fn static int mrpc_sgc_GetTpPortCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get TP counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetTpPortCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret = PPSGC_RC_SUCCESS; struct PpsgcTpPortCounters *argPpsgcTpPortCounters = (struct PpsgcTpPortCounters *)arg; struct PpsgcTpPortCounters *repPpsgcTpPortCounters = (struct PpsgcTpPortCounters *)rep; WARN_ON(!sgcServerDb->callbacks); memset(repPpsgcTpPortCounters, 0, sizeof(struct PpsgcTpPortCounters)); if (strncmp(argPpsgcTpPortCounters->ifName, IFNAME_MGMTIF_0, strlen(IFNAME_MGMTIF_0)) != 0) { ret = AddTpPortCounters(argPpsgcTpPortCounters->ifName, repPpsgcTpPortCounters); pr_debug("%s(%s)=%d\n", __func__, argPpsgcTpPortCounters->ifName, ret); } else { char *ifaces[] = { IFNAMES_LANPORTS, 0 }; Uint64 rx_packets; int i, tmp; for (i = 0; ifaces[i]; i++) { tmp = AddTpPortCounters(ifaces[i], repPpsgcTpPortCounters); if (tmp) ret = tmp; } /* * Because the lan ports are vlan devices, we need to reduce * the rx_byte by the 4 byte per packet (vlan header). * * 2018-11-28, calle */ rx_packets = repPpsgcTpPortCounters->tpCounters.rx_unicast_pkt + repPpsgcTpPortCounters->tpCounters.rx_multicast_pkt + repPpsgcTpPortCounters->tpCounters.rx_broadcast_pkt; repPpsgcTpPortCounters->tpCounters.rx_byte -= rx_packets * VLAN_HDR_SIZE; pr_debug("%s(%s)=%d (lan ports)\n", __func__, argPpsgcTpPortCounters->ifName, ret); } #define PRINTVAL64(member) pr_debug("%-16s %16llu\n", #member, repPpsgcTpPortCounters->tpCounters.member) PRINTVAL64(rx_byte); PRINTVAL64(rx_unicast_pkt); PRINTVAL64(rx_broadcast_pkt); PRINTVAL64(rx_multicast_pkt); PRINTVAL64(rx_discard_pkt); PRINTVAL64(tx_byte); PRINTVAL64(tx_unicast_pkt); PRINTVAL64(tx_broadcast_pkt); PRINTVAL64(tx_multicast_pkt); PRINTVAL64(tx_discard_pkt); #undef PRINTVAL64 TpPortCounters2be(repPpsgcTpPortCounters); return ret; } #endif // CONFIG_AVM_RDKB_MODEM_OSS_11_IFTABLE_DOT1DTPPORT_FIX /**************************************************************************/ /*! \fn static int mrpc_sgc_GetSfCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Get SF counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_GetSfCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { int ret; struct PpsgcSfCounters ppsgcSfCounters = {0}; struct PpsgcSfCounters *argPpsgcSfCounters = (struct PpsgcSfCounters *)arg; struct PpsgcSfCounters *repPpsgcSfCounters = (struct PpsgcSfCounters *)rep; WARN_ON(!sgcServerDb->callbacks); strncpy(ppsgcSfCounters.ifName, argPpsgcSfCounters->ifName, sizeof(ppsgcSfCounters.ifName)-1); ppsgcSfCounters.sfIndex = ntohl(argPpsgcSfCounters->sfIndex); ppsgcSfCounters.clearFlag = ntohl(argPpsgcSfCounters->clearFlag); ret = sgcServerDb->callbacks->PPSGC_Db_GetSfCounters(&ppsgcSfCounters); repPpsgcSfCounters->sfCounters.fwd_pkts = cpu_to_be64(ppsgcSfCounters.sfCounters.fwd_pkts); repPpsgcSfCounters->sfCounters.drp_cnt = cpu_to_be64(ppsgcSfCounters.sfCounters.drp_cnt); return ret; } /**************************************************************************/ /*! \fn static int mrpc_sgc_PrintTpPortCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Print TP port counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_PrintTpPortCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_PrintTpPortCounters(); } /**************************************************************************/ /*! \fn static int mrpc_sgc_PrintIfCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Print IF counters. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_PrintIfCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_PrintIfCounters(); } /**************************************************************************/ /*! \fn static int mrpc_sgc_PrintGroupCounters * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Print group counters statistics. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_PrintGroupCounters (void *arg, ssize_t arglen, void *rep, ssize_t replen) { WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_PrintGroupCounters(); } /**************************************************************************/ /*! \fn static int mrpc_sgc_RestartGroupCounter * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Restart group counter. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_RestartGroupCounter (void *arg, ssize_t arglen, void *rep, ssize_t replen) { unsigned int *argGroupCounterId = (unsigned int *)arg; unsigned int tmpGroupCounterId; unsigned short resGroupCounterId; tmpGroupCounterId = *argGroupCounterId; tmpGroupCounterId = ntohl(tmpGroupCounterId); resGroupCounterId = tmpGroupCounterId; WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_RestartGroupCounterId (resGroupCounterId); } /**************************************************************************/ /*! \fn static int mrpc_sgc_ReleaseGroupCounterIdsTable * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Release group counter IDs table. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_ReleaseGroupCounterIdsTable (void *arg, ssize_t arglen, void *rep, ssize_t replen) { unsigned int groupIndex; struct PpsgcGroupCountersTable groupCountersTable = {0}; struct PpsgcGroupCountersTable *argGroupCountersTable = (struct PpsgcGroupCountersTable *)arg; groupCountersTable.numOfGroups = ntohl(argGroupCountersTable->numOfGroups); for (groupIndex=0; (groupIndexgroupCounterIds[groupIndex]); } WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_ReleaseGroupCounterIdsTable (&groupCountersTable); } /**************************************************************************/ /*! \fn static int mrpc_sgc_DelGroupCountersTableSessions * (void *arg, ssize_t arglen, void *rep, ssize_t replen) ************************************************************************** * \brief Delete sessions list of Group Counter IDs table. * \param[in] arg - Pointer to arguments buffer. * \param[in] arglen - Arguments length. * \param[out] rep - Pointer to reply buffer. * \param[out] replen - Reply length. * \return 0 for success, error code otherwise. **************************************************************************/ static int mrpc_sgc_DelGroupCountersTableSessions (void *arg, ssize_t arglen, void *rep, ssize_t replen) { unsigned int groupIndex; struct PpsgcGroupCountersSessionsToDel groupCountersSessionsList = {0}; struct PpsgcGroupCountersSessionsToDel *argGroupCountersSessionsList = (struct PpsgcGroupCountersSessionsToDel *)arg; groupCountersSessionsList.groupCounterIdToRelease = ntohs(argGroupCountersSessionsList->groupCounterIdToRelease); groupCountersSessionsList.groupCounterIdToRestart = ntohs(argGroupCountersSessionsList->groupCounterIdToRestart); groupCountersSessionsList.groupCounterIdsTable.numOfGroups = ntohl(argGroupCountersSessionsList->groupCounterIdsTable.numOfGroups); for (groupIndex=0; (groupIndexgroupCounterIdsTable.groupCounterIds[groupIndex]); } WARN_ON(!sgcServerDb->callbacks); return sgcServerDb->callbacks->PPSGC_Db_DeleteGroupCountersTableSessions (&groupCountersSessionsList); } static struct mrpc_procinfo sgc_server_procs[] = { /* Request, Handle function, Argument length, Reply length */ MRPC_PROCINFO_ENTRY(SGC_ALLOC_GROUP_COUNTER_ID_PROC, mrpc_sgc_AllocGroupCounter, 0, sizeof(unsigned int)), MRPC_PROCINFO_ENTRY(SGC_RELEASE_GROUP_COUNTER_ID_PROC, mrpc_sgc_ReleaseGroupCounter, sizeof(unsigned int), 0), MRPC_PROCINFO_ENTRY(SGC_DEL_GROUP_COUNTER_SESSIONS_PROC, mrpc_sgc_DelGroupCounterSessions, sizeof(unsigned int), 0), MRPC_PROCINFO_ENTRY(SGC_GET_GROUP_COUNTER_AMOUNT_PROC, mrpc_sgc_GetGroupCounterAmount, sizeof(unsigned int), sizeof(struct PpsgcPpCounters)), MRPC_PROCINFO_ENTRY(SGC_GET_IF_COUNTERS_PROC, mrpc_sgc_GetIfCounters, sizeof(struct PpsgcIfCounters), sizeof(struct PpsgcIfCounters)), MRPC_PROCINFO_ENTRY(SGC_GET_TP_PORT_COUNTERS_PROC, mrpc_sgc_GetTpPortCounters, sizeof(struct PpsgcTpPortCounters), sizeof(struct PpsgcTpPortCounters)), MRPC_PROCINFO_ENTRY(SGC_GET_SF_COUNTERS_PROC, mrpc_sgc_GetSfCounters, sizeof(struct PpsgcSfCounters), sizeof(struct PpsgcSfCounters)), MRPC_PROCINFO_ENTRY(SGC_PRINT_TPPORT_COUNTERS_PROC, mrpc_sgc_PrintTpPortCounters, 0, 0), MRPC_PROCINFO_ENTRY(SGC_PRINT_IF_COUNTERS_PROC, mrpc_sgc_PrintIfCounters, 0, 0), MRPC_PROCINFO_ENTRY(SGC_PRINT_GROUP_COUNTERS_PROC, mrpc_sgc_PrintGroupCounters, 0, 0), MRPC_PROCINFO_ENTRY(SGC_RESTART_GROUP_COUNTER_ID_PROC, mrpc_sgc_RestartGroupCounter, sizeof(unsigned int), 0), MRPC_PROCINFO_ENTRY(SGC_RELEASE_GROUP_COUNTERS_TABLE_PROC, mrpc_sgc_ReleaseGroupCounterIdsTable, sizeof(struct PpsgcGroupCountersTable), 0), MRPC_PROCINFO_ENTRY(SGC_DEL_GROUP_COUNTERS_SESSIONS_TABLE_PROC, mrpc_sgc_DelGroupCountersTableSessions, sizeof(struct PpsgcGroupCountersSessionsToDel), 0), }; /**************************************************************************/ /*! \fn static ssize_t status_show * (struct device *dev, struct device_attribute *attr, char *buf) ************************************************************************** * \brief Status show function. * \param[in] * \param[out] * \return 0 for success, error code otherwise. **************************************************************************/ static ssize_t status_show (struct device *dev, struct device_attribute *attr, char *buf) { struct SgcServerPrivate *sgcServer = dev_get_drvdata(dev); if (!sgcServer) return -EINVAL; return scnprintf(buf, PAGE_SIZE, "status ok"); } static DEVICE_ATTR(status, S_IRUGO, status_show, NULL); static struct attribute *sgc_attrs[] = { &dev_attr_status.attr, NULL }; static struct attribute_group sgc_attrs_group = { .attrs = sgc_attrs, }; /**************************************************************************/ /*! \fn static int sgc_probe(struct platform_device*) ************************************************************************** * \brief Probe function. * \param[in] pdev - Ponter to plafrom device * \param[out] * \0 for success, error code otherwise. **************************************************************************/ static int sgc_probe(struct platform_device *pdev) { int ret; sgcServerDb = devm_kzalloc(&pdev->dev, sizeof(*sgcServerDb), GFP_KERNEL); if (!sgcServerDb) { pr_err("memory allocation failed\n"); return -ENOMEM; } dev_set_drvdata(&pdev->dev, sgcServerDb); sgcServerDb->pdev = pdev; ret = sysfs_create_group(&sgcServerDb->pdev->dev.kobj, &sgc_attrs_group); if (ret) { pr_err("sysfs_create_group failed (ret=%d)", ret); return ret; } sgcServerDb->mrpc = mrpc_server_register (MRPC_RESERVED_ID_SGC, "Session Group Counter", sgc_server_procs, ARRAY_SIZE(sgc_server_procs)); if (!sgcServerDb->mrpc) { pr_err("failed to register sgc\n"); ret = -ENODEV; goto out_remove_group; } return 0; out_remove_group: sysfs_remove_group(&sgcServerDb->pdev->dev.kobj, &sgc_attrs_group); return ret; } /**************************************************************************/ /*! \fn static int sgc_remove(struct platform_device*) ************************************************************************** * \brief Remove function. * \param[in] pdev - Pointer to platform device * \param[out] None * \0 for success, error code otherwise. **************************************************************************/ static int sgc_remove(struct platform_device *pdev) { struct SgcServerPrivate *priv = platform_get_drvdata(pdev); if (priv->callbacks) kfree(priv->callbacks); mrpc_server_unregister(priv->mrpc); sysfs_remove_group(&priv->pdev->dev.kobj, &sgc_attrs_group); dev_set_drvdata(&pdev->dev, NULL); sgcServerDb = NULL; return 0; } static struct platform_driver sgc_driver = { .driver = { .name = "sgc_server", }, .probe = sgc_probe, .remove = sgc_remove, }; static struct platform_device *sgc_device; /**************************************************************************/ /*! \fn static int __init sgc_server_init(void) ************************************************************************** * \brief Init function. * \param[in] None * \param[out] None * \0 for success, error code otherwise. **************************************************************************/ static int sgc_server_init(void) { int ret; ret = platform_driver_register(&sgc_driver); if (ret < 0) { pr_err("Failed to register sgc platform driver: %d\n", ret); return ret; } pr_debug("sgc server platform driver is registered"); sgc_device = platform_device_register_simple("sgc_server", -1, NULL, 0); if (IS_ERR(sgc_device)) { pr_err("Failed to register sgc platform device\n"); platform_driver_unregister(&sgc_driver); return PTR_ERR(sgc_device); } dev_info(&sgc_device->dev, "platform device is registered\n"); return 0; } /**************************************************************************/ /*! \fn static void __exit sgc_server_exit(void) ************************************************************************** * \brief Exit function. * \param[in] None * \param[out] None **************************************************************************/ static void __exit sgc_server_exit(void) { platform_device_unregister(sgc_device); platform_driver_unregister(&sgc_driver); } static_notifier_module_init(mrpc_ready, sgc_server_init); module_exit(sgc_server_exit); MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION("PPSGC mrpc server"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0");