/* GPL LICENSE SUMMARY Copyright(c) 2017 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 "linux/ti_pp_path.h" #include "linux/mcs_ctl.h" #include MODULE_AUTHOR("Intel Corporation"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Mac Count List Module"); /**************************************************************************/ /* DEFINES: */ /**************************************************************************/ #define BUFFER_FOR_PRINTF_SIZE 1000 /* global buff size*/ static char buff[BUFFER_FOR_PRINTF_SIZE]; static char tmp_buff[BUFFER_FOR_PRINTF_SIZE]; #define MCS_LIST_SIZE 512 #define MCS_SUCCESS 0 #define MCS_FAILURE -1 #define MCS_CDEV_MIN_MINOR 0 #define MCS_CDEV_NUM_DEVICES 1 #define MCS_CDEV_NAME "Mac_Count_Satistics" /**************************************************************************/ /* LOCAL VARIABLES: */ /**************************************************************************/ struct proc_dir_entry *mcsctl = NULL; struct proc_dir_entry *dir_mcsbase = NULL; Uint32 g_proc_mcs_handle = AVALANCHE_PP_MAX_ACCELERATED_SESSIONS; /* Add MAC Address to MCS (Mac Count Satistics) DB for statistics tracking */ static int mcsAddCpeMacAddr (Uint8 *macAddr, int *result); /* Delete MAC Address to MCS (Mac Count Satistics) DB for statistics tracking */ static void mcsDelCpeMacAddr (Uint8 *macAddr, int *result); /* Flush MCS (Mac Count Satistics) DB */ static void mcsFlushTable (int *result); /* Print MCS (Mac Count Satistics) DB satistics for all Added MAC address to DB */ static int mcsGetSatistics(int *len, char *bufCopy, int lengthToCopy); static long __mcsIoctl ( struct file * filp , unsigned int cmd , unsigned long arg ); static struct cdev *mcs_cdev; static dev_t mcs_dev_numbers; static struct file_operations mcs_cdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = __mcsIoctl, }; #define BUFF_FREE(len) ( BUFFER_FOR_PRINTF_SIZE - (len)) /* BUFF_FREE returns the number of free bytes in global buffer */ #define FOR_ALL_PIDS(i) for (; i < AVALANCHE_PP_MAX_PID; i++) #define LIST_FOR_EACH(pos, head) for (; prefetch(pos->next), (pos) != (head); (pos) = (pos->next) ) #define WR_TO_PAGE if (len < count) { copy_to_user(user_buf+curr_off, buff, len); curr_off += len; count -= len ; } else { return curr_off; } /* write to page*/ #define CHECK_SNPRINTF(val, len) if (val > 0) (len) += (val) /* check if snprintf seccess*/ static Uint8 g_proc_mcsAction_cmd[100]; static Uint8* g_proc_mcsAction_argv[10]; /* start session notification Callback */ MCS_START_SESSION mcs_ctl_start_session_notification_cb = NULL; /* delete session notification Callback */ MCS_DELETE_SESSION mcs_ctl_delete_session_notification_cb = NULL; Uint32 USPacketCount = 0; /* Satistics */ Uint32 DSPacketCount = 0; Uint64 USByteCount = 0; Uint64 DSByteCount = 0; static long __mcsIoctl ( struct file * filp , unsigned int cmd , unsigned long arg ) { return MCS_SUCCESS; } /*====================== MCS and MCE Database Definitions =================== */ static LIST_HEAD(macCountListHead); typedef struct macCountElement { Uint8 macAddress[6]; /* MAC address for each element */ unsigned long elementAge; /* represent this Element Age in the system */ Uint32 markedByUser; /* This MCE was added by the command mcsAction Add */ Uint32 USPacketCount; /* Satistics */ Uint32 DSPacketCount; Uint64 USByteCount; Uint64 DSByteCount; struct MCSCountSessionEntry_t *activeSessionList; /* pointer to session list */ } macCountElement_T; typedef struct _macCountListEntry { struct list_head list; macCountElement_T element; } _macCountListEntry_T; //====================== Session Data Base =================== typedef struct MCSCountSessionEntry { Uint32 sessionHandle; Uint8 direction; void* mcePtr; struct MCSCountSessionEntry_t *nextSession; struct MCSCountSessionEntry_t *prvSession; } MCSCountSessionEntry_t; typedef struct MCSCountersDataBase { MCSCountSessionEntry_t MCSSessionsTable[ AVALANCHE_PP_MAX_ACCELERATED_SESSIONS ]; } MCSCountersDataBase_t; static MCSCountersDataBase_t mac_counters_db; Uint32 numMarkedMCE = 0; /*Number of Marked MCE's by users*/ Uint32 numOfMCE = 0; /*Number of MCE's */ Uint8 printAction = 0; // While print Action it is not allowed to del/add entry only session can be added Uint8 getSatisticsAction = 0; // While print Action it is not allowed to del/add entry only session can be added static unsigned long lastRxCounterResetTimeInJiffies = 0; typedef enum sessionDirection { DIR_UNKNOWN = 0, DIR_DS, DIR_US, } SESSION_DIRECTION; static int RemoveSessionsFromActiveList(_macCountListEntry_T *entry); /************************************************************************** * FUNCTION NAME : FindEntryByMacAddr ************************************************************************** * DESCRIPTION : * Gets mac address and check if is valid in the MCS list, if Valid MAC return the pointer to that MCE, otherwise false * param[in] mac address * param[in] mac element entry * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int FindEntryByMacAddr(Uint8 *macAddr, _macCountListEntry_T **entry) { struct list_head *pos; _macCountListEntry_T *curr=NULL; int result = 0; /* find a place in the list according to the Mac Address */ list_for_each(pos, &macCountListHead) { curr = list_entry(pos, _macCountListEntry_T, list); result = memcmp (&(curr->element.macAddress[0]), &(macAddr[0]), 6); if ( result == 0) break; } if (pos != &macCountListHead) { *entry = curr; return MCS_SUCCESS; } else return MCS_FAILURE; } /*==========================================================================*/ /*=============================== Add Functions ===========================*/ /*==========================================================================*/ /************************************************************************** * FUNCTION NAME : setMceData ************************************************************************** * DESCRIPTION : * Copy new Element Data to the element allocated in the list * param[in] List entry * param[in] Mac element entry * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static void setMceData(_macCountListEntry_T *entry, macCountElement_T *element) { PAL_osMemCopy(&(entry->element), element, sizeof(macCountElement_T)); } /************************************************************************** * FUNCTION NAME : createNewMce ************************************************************************** * DESCRIPTION : * Allocated new Element Data MCE of the list * param[in] List entry * param[in] Mac element entry * RETURNS : * * **************************************************************************/ static int createNewMce(_macCountListEntry_T **entry, macCountElement_T *element) { PAL_Result res; res = PAL_osMemAlloc(0, sizeof(_macCountListEntry_T), 0, (Ptr *)entry); if (res != PAL_SOK) { printk (KERN_DEBUG " ERROR: Problem with Allocate Memory for new MCE \n"); return MCS_FAILURE; } setMceData(*entry, element); return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsAddMce ************************************************************************** * DESCRIPTION : * Copy new Element Data to the element allocated and add ti to the MCS list * param[in] Mac Element * param[in] marked by user * RETURNS : * Pointer to the new structure * **************************************************************************/ static _macCountListEntry_T* mcsAddMce ( macCountElement_T *newMCE, Uint8 markedByUser) { Uint32 lockKey; struct list_head *pos; _macCountListEntry_T *curr=NULL, *new; Uint8 i=0; /* Find a place in the list based Mac address */ list_for_each(pos, &macCountListHead) { curr = list_entry(pos, _macCountListEntry_T, list); for (i=0; i<6; i++) { if (curr->element.macAddress[i] >= newMCE->macAddress[i]) break; } } /*Create new list entry (MCE) */ createNewMce (&new, newMCE); /* insert before the current entry */ PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); list_add(&new->list, pos->prev); if(markedByUser) { /* MCE Added by the user */ numMarkedMCE++; } /* Increment Number of elements */ numOfMCE++; PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return new; } /************************************************************************** * FUNCTION NAME : RemoveOldestMce ************************************************************************** * DESCRIPTION : * In case all list is occupied (MCS_LIST_SIZE Elements) and new Add request for new MAC is done by the user, * Or new session with new MAC Address was added. * In that case we will find the most "old" Element not added by user (but opened by session) and remove that element * param[in] None * param[in] None * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int RemoveOldestMce(void) { Uint32 lockKey; _macCountListEntry_T *curr=NULL, *delCanditate = NULL; struct list_head *pos; unsigned long smallestValJiffies = 0xFFFFFFFF; /* validate that we are not during Print command */ PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); if (printAction || getSatisticsAction) { /* Somebody is printing the list, we can't delete */ printk (KERN_DEBUG " RemoveOldestMce: Somebody is printing the list, we can't delete \n"); PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return MCS_FAILURE; } PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); /* Retrieve the most Oldest MCE in the list - This is done by find the element with the most "Old" jiffies */ list_for_each(pos, &macCountListHead) { curr = list_entry(pos, _macCountListEntry_T, list); if (curr->element.elementAge != 0) { if(curr->element.elementAge < smallestValJiffies) { smallestValJiffies = curr->element.elementAge; delCanditate = curr; } } } if ((delCanditate !=NULL) && (!(delCanditate->element.markedByUser))) { /*Enter here remove of the session Active List */ RemoveSessionsFromActiveList(delCanditate); printk (KERN_DEBUG " Remove the oldest Element not marked by user [%lu] \n ",delCanditate->element.elementAge); PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); list_del(&delCanditate->list); numOfMCE--; PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); PAL_osMemFree(0, delCanditate, sizeof(_macCountListEntry_T)); } return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsAddCpeMacAddr ************************************************************************** * DESCRIPTION : * User API - This function will check if need to add MCE to the MCS table * the function get Mac address, if it exist , it will be marked as user add this. * If it is not exist, it will be added. * param[in] mac address * param[in] result * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcsAddCpeMacAddr (Uint8 *macAddr, int *result) { Uint32 lockKey; macCountElement_T element; _macCountListEntry_T *list; int result1 = 0; PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); if (printAction || getSatisticsAction) { /* Somebody is printing the list, we can't add */ *result = MCS_FAILURE; printk (KERN_DEBUG " mcsAddCpeMacAddr: Somebody is printing the list, we can't delete \n"); PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return MCS_FAILURE; } PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); /* Find if this mac Address is valid in our MCS dataBase*/ result1 = FindEntryByMacAddr (&(macAddr[0]), &list); /* check if that was marked by user */ if (result1 == MCS_FAILURE ) // if this entry not valid { /* If there is no place then return error */ if (numMarkedMCE == MCS_LIST_SIZE) { /* No space Left */ *result = MCS_FAILURE; printk (KERN_DEBUG " The table is full - need to remove entries \n"); return MCS_FAILURE; } /* If numMarkedMCE is less than MCS_LIST_SIZE and numOfMce is MCS_LIST_SIZE Then we need to move the Oldest element not marked by user */ if ((numMarkedMCE < MCS_LIST_SIZE) && (numOfMCE == MCS_LIST_SIZE)) { /* remove the Oldest element */ *result = RemoveOldestMce(); if (*result == MCS_FAILURE) return MCS_FAILURE; } memcpy(&(element.macAddress[0]), &(macAddr[0]), 6); element.markedByUser = 1; element.activeSessionList = NULL; /* pointer to session list */ element.USPacketCount = 0; element.DSPacketCount = 0; element.USByteCount = 0; element.DSByteCount = 0; element.elementAge = 0; mcsAddMce(&element, element.markedByUser); /* Add this element to the linked list */ } // If it was marked by user than define it in the list. if (result1 == 0) { list->element.markedByUser = 1; list->element.elementAge = 0; numMarkedMCE++; } *result = MCS_SUCCESS; return MCS_SUCCESS; } /*=============================== Del Functions ===========================*/ /************************************************************************** * FUNCTION NAME : RemoveSessionsFromActiveList ************************************************************************** * DESCRIPTION : * When delete element need to remove the corresponding sessions * param[in] mac element entry * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int RemoveSessionsFromActiveList(_macCountListEntry_T *entry) { macCountElement_T* matchMce = &(entry->element); MCSCountSessionEntry_t *currentSession = (MCSCountSessionEntry_t *) matchMce->activeSessionList; Uint32 sessionHandle=0; if (currentSession == NULL) { return MCS_SUCCESS; } while ((currentSession != NULL)) { sessionHandle = mac_counters_db.MCSSessionsTable[sessionHandle].sessionHandle; mac_counters_db.MCSSessionsTable[sessionHandle].mcePtr = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].direction = DIR_UNKNOWN; currentSession = (MCSCountSessionEntry_t *) mac_counters_db.MCSSessionsTable[sessionHandle].nextSession; mac_counters_db.MCSSessionsTable[sessionHandle].prvSession = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].nextSession = NULL; } return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsDelCpeMacAddr ************************************************************************** * DESCRIPTION : * When delete element need to remove the corresponding sessions * param[in] mac address * param[in] Result * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ void mcsDelCpeMacAddr (Uint8 *macAddr, int *result) { _macCountListEntry_T *entry; Uint32 lockKey; int result1 = 0; PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); if (printAction || getSatisticsAction) { /* Somebody is printing the list, we can't add */ *result = MCS_FAILURE; printk (KERN_DEBUG " mcsDelCpeMacAddr - Somebody is printing the list, we can't add \n"); PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return; } PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); // Find if this mac Address is valid in our MCS dataBase result1 = FindEntryByMacAddr (macAddr, &entry); // Delete only if this Entry Valid, if ((result1 == MCS_SUCCESS) && (entry->element.markedByUser)) { // Enter here remove of the session Active List. RemoveSessionsFromActiveList(entry); PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); list_del(&entry->list); numMarkedMCE --; numOfMCE--; PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); PAL_osMemFree(0, entry, sizeof(_macCountListEntry_T)); *result = MCS_SUCCESS; } else if (result1 == MCS_FAILURE) // Not valid entry { printk (KERN_DEBUG " mcsDelCpeMacAddr - Not valid entry \n"); *result = MCS_FAILURE; } } /*=============================== Print Functions ===========================*/ /************************************************************************** * FUNCTION NAME : findMarkedMce ************************************************************************** * DESCRIPTION : * When delete element need to remove the corresponding sessions * param[in] should return the num of entries * param[in] ** MCE list to return * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int findMarkedMce (Uint16 *num_entries, macCountElement_T ** MCE_list) { struct list_head *pos; _macCountListEntry_T *curr=NULL; Uint16 count = 0; list_for_each(pos, &macCountListHead) { curr = list_entry(pos, _macCountListEntry_T, list); if (curr->element.markedByUser) { if (MCE_list) { *MCE_list++ = &(curr->element); } count++; } } *num_entries = count; return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : getMceSatistics ************************************************************************** * DESCRIPTION : * get all the parameters per MCE * param[in] should return the num of entries * param[in] ** MCE list to return * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int getMceSatistics (macCountElement_T *entry) { MCSCountSessionEntry_t *currSessionEntry = NULL; USPacketCount = 0; USByteCount = 0; DSPacketCount = 0; DSByteCount = 0; /* get matched of current sessions */ if (entry->activeSessionList != NULL) { currSessionEntry = (MCSCountSessionEntry_t *) entry->activeSessionList; while (currSessionEntry != NULL) { AVALANCHE_PP_SESSION_STATS_t sessionStats; if (PP_RC_SUCCESS != avalanche_pp_get_stats_session(currSessionEntry->sessionHandle, &sessionStats)) { return MCS_FAILURE; } /* Update the stats */ if (currSessionEntry->direction == DIR_US) // UPLINK { USPacketCount += sessionStats.packets_forwarded; USByteCount += sessionStats.bytes_forwarded; } else if (currSessionEntry->direction == DIR_DS) // Downlink { DSPacketCount += sessionStats.packets_forwarded; DSByteCount += sessionStats.bytes_forwarded; } currSessionEntry = (MCSCountSessionEntry_t *) currSessionEntry->nextSession; } } USPacketCount += entry->USPacketCount; // what was saved before USByteCount += entry->USByteCount; // what was saved before DSPacketCount += entry->DSPacketCount; // what was saved before DSByteCount += entry->DSByteCount; // what was saved before return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsGetSatistics ************************************************************************** * DESCRIPTION : * get all the the satistics - User API * param[in] length to return * param[in] Buffer to copy to * param[in] length to copy * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcsGetSatistics(int *len, char *bufCopy, int lengthToCopy) { macCountElement_T *MCE_list[MCS_LIST_SIZE]; Uint16 num_entries = 0; Uint16 mceIndex = 0; int prntRtrn = 0; int result=0; if (bufCopy == NULL || lengthToCopy == 0) { printk (KERN_DEBUG " mcsGetSatistics - problem with bufCopy %x , lengthToCopy\n", bufCopy, lengthToCopy); return MCS_FAILURE; } if (!printAction && !getSatisticsAction) { findMarkedMce (&num_entries, MCE_list ); getSatisticsAction = 1; } else { printk (KERN_DEBUG " mcsGetSatistics -somebody is printing \n"); return MCS_FAILURE; // somebody is printing } while (mceIndex < num_entries) { /* Get the MCE statistics. */ result = getMceSatistics (MCE_list[mceIndex]); if ( result == MCS_FAILURE) { mceIndex++; } else { /* Print the statistics on the console. */ prntRtrn = snprintf(bufCopy+ *len, (lengthToCopy - *len), " %02X:%02X:%02X:%02X:%02X:%02X: |", MCE_list[mceIndex]->macAddress[0], MCE_list[mceIndex]->macAddress[1], MCE_list[mceIndex]->macAddress[2], MCE_list[mceIndex]->macAddress[3], MCE_list[mceIndex]->macAddress[4], MCE_list[mceIndex]->macAddress[5]);CHECK_SNPRINTF(prntRtrn, *len); prntRtrn = snprintf(bufCopy+ *len, (lengthToCopy - *len), " %u |", DSPacketCount);CHECK_SNPRINTF(prntRtrn, *len); prntRtrn = snprintf(bufCopy+ *len, (lengthToCopy - *len), " %llu |", DSByteCount);CHECK_SNPRINTF(prntRtrn, *len); prntRtrn = snprintf(bufCopy+ *len, (lengthToCopy - *len), " %u |", USPacketCount);CHECK_SNPRINTF(prntRtrn, *len); prntRtrn = snprintf(bufCopy+ *len, (lengthToCopy - *len), " %llu | \n", USByteCount);CHECK_SNPRINTF(prntRtrn, *len); /* check not overflow */ if(*len > (lengthToCopy - 100)) mceIndex = num_entries; mceIndex++; } } num_entries = 0; mceIndex = 0; getSatisticsAction = 0; return MCS_SUCCESS; } /* for debug */ void printMcsGetSatistics(void) { int len2 = 0, i=0, lenToCopy = 4000; mcsGetSatistics(&len2, tmp_buff, lenToCopy); for (i=0; inext; list_del(&curr->list); PAL_osMemFree(0, curr, sizeof(_macCountListEntry_T)); } numOfMCE = 0; numMarkedMCE = 0; printAction = 0; getSatisticsAction = 0; PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); memset((void *)&mac_counters_db, 0, sizeof(MCSCountersDataBase_t)); return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsFlushTable ************************************************************************** * DESCRIPTION : * Flush all table- user API * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ void mcsFlushTable (int *result) { Uint32 lockKey; PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); if (printAction || getSatisticsAction) { /* Somebody is printing the list, we can't add */ *result = MCS_FAILURE; printk (KERN_DEBUG " mcsFlushTable - somebody is printing \n"); PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return; } PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); *result = McsClearAll(); } /*=============================== Dbg Functions ===========================*/ static void printEachMce(macCountElement_T *entry) { Uint32 USPacketCount = 0; /* Satistics */ Uint32 DSPacketCount = 0; Uint64 USByteCount = 0; Uint64 DSByteCount = 0; // MAC Address printk( "%02X:%02X:%02X:%02X:%02X:%02X \n ", entry->macAddress[0],entry->macAddress[1],entry->macAddress[2], entry->macAddress[3],entry->macAddress[4],entry->macAddress[5]); /* get matched of current sessions */ if (entry->activeSessionList != NULL) { MCSCountSessionEntry_t *currSessionEntry = (MCSCountSessionEntry_t *) entry->activeSessionList; while (currSessionEntry != NULL) { AVALANCHE_PP_SESSION_STATS_t sessionStats; if (PP_RC_SUCCESS != avalanche_pp_get_stats_session(currSessionEntry->sessionHandle, &sessionStats)) { printk (KERN_DEBUG " No stats for sessionHandle %d \n ",currSessionEntry->sessionHandle); return; } if (currSessionEntry->direction == DIR_US) // UPLINK { printk(KERN_DEBUG " sessionHandle US - %d ", currSessionEntry->sessionHandle); printk(KERN_DEBUG " Packets: %u ", sessionStats.packets_forwarded); printk(KERN_DEBUG " Bytes: %llu \n", sessionStats.bytes_forwarded); USPacketCount += sessionStats.packets_forwarded; USByteCount += sessionStats.bytes_forwarded; } else if (currSessionEntry->direction == DIR_DS) // Downlink { printk(KERN_DEBUG " sessionHandle DS - %d ", currSessionEntry->sessionHandle); printk(KERN_DEBUG " Packets: %u ", sessionStats.packets_forwarded); printk(KERN_DEBUG " Bytes: %llu \n", sessionStats.bytes_forwarded); DSPacketCount += sessionStats.packets_forwarded; DSByteCount += sessionStats.bytes_forwarded; } currSessionEntry = (MCSCountSessionEntry_t *) currSessionEntry->nextSession; } } USPacketCount += entry->USPacketCount; DSPacketCount += entry->DSPacketCount; USByteCount += entry->USByteCount; DSByteCount += entry->DSByteCount; printk("marked by user: %d | ", entry->markedByUser); printk("elementAge: [%lu] | ", entry->elementAge); printk("%u |", DSPacketCount); printk("%llu |", DSByteCount); printk("%u |", USPacketCount); printk("%llu | \n\n", USByteCount); } static int printAllMcsTable(void) { int i=0; struct list_head *pos; _macCountListEntry_T *curr=NULL; printk(KERN_DEBUG "\n========== MAC Count Data Base========== \n"); printk(KERN_DEBUG "Mac Address |"); printk(KERN_DEBUG "rx Packets |"); printk(KERN_DEBUG "rx Bytes |"); printk(KERN_DEBUG "tx Packets |"); printk(KERN_DEBUG "tx Bytes | \n"); list_for_each(pos, &macCountListHead) { curr = list_entry(pos, _macCountListEntry_T, list); printk (" %d | ",i++); printEachMce(&(curr->element)); } printk(KERN_DEBUG "Printed ALL | \n"); return MCS_SUCCESS; } void mcsPrintTable (int *result) { printAllMcsTable(); } /*=============================== File operation Functions ===========================*/ void mcsBuildUnitTestTable (void) { int result; Uint8 macAddr[6]; int i=0; int j=0, k=0; macAddr[0] = 0x11; macAddr[1] = 0x22; macAddr[2] = 0x33; macAddr[3] = 0x44; macAddr[4] = 0x55; for (i=0; i<511; i++,j++) { if(i == 255) { macAddr[4] = 0x56; j=0; } macAddr[5] = j; mcsAddCpeMacAddr(&(macAddr[0]), &result); } } /*=============================== File operation Functions ===========================*/ static ssize_t MCSACTION_write_proc(struct file *fp, const char __user * buf, size_t count, loff_t *ppos) { int ret_val = 0; if (count > 100) { printk(KERN_ERR "\n%s[%d]: Buffer Overflow\n", __FUNCTION__, __LINE__); return -EFAULT; } if (copy_from_user(g_proc_mcsAction_cmd, buf, count)) { return -EFAULT; } g_proc_mcsAction_cmd[count]='\0'; ret_val = count; return ret_val; } static int MCSACTION_read_proc(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { /* struct list_head *pos; _macCountListEntry_T curr; */ int len = 0; int curr_off = 0; int prntRtrn; int argc = 0; char * ptr_next_tok; char * delimitters = " \n\t"; char * ptr_cmd; Uint8 mac[6]; int result; // debug the GetS int len2 = 0; int i=0; static Uint16 num_entries = 0; static Uint16 mceIndex = 0; static macCountElement_T *MCE_list[MCS_LIST_SIZE]; static Uint8 endOfData = 0; if (endOfData == 1) { endOfData = 0; mceIndex = 0; num_entries = 0; return MCS_SUCCESS; } memset((void *)&g_proc_mcsAction_argv[0], 0, sizeof(g_proc_mcsAction_argv)); ptr_next_tok = g_proc_mcsAction_cmd; /* Extract the first command */ /* Parse all the commands typed */ while (1) { ptr_cmd = strsep(&ptr_next_tok, delimitters); if (ptr_cmd == NULL || *ptr_cmd == NULL ) { /* 'strsep' returns null if there was no tok when it gets to '\0', Or the tok was only delimitter char (empty tok) */ break; } g_proc_mcsAction_argv[argc++] = ptr_cmd; if (ptr_next_tok == NULL) { /* no next tok*/ break; } /* Validate if the user entered more commands.*/ if (argc >= 10) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect, too many parameters dropping the command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } } if (argc == 0) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect, no command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } if (strncmp(g_proc_mcsAction_argv[0], "Add", strlen("Add")) == 0) { unsigned int mac_len = 0; Int8 *endptr; Uint8 counter = 0; if (argc != 2) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect number of parameters for mac command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } endptr = g_proc_mcsAction_argv[1]; /* Copy the MAC Address */ while (True) { Uint8 val; val = (Uint8)simple_strtol(endptr, (char**)&endptr, 16); if ((*endptr != ':') && (*endptr != '\0')) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Add command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } else if (*endptr == ':') { counter++; if ((*(endptr + 1)) == '\0') { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Add command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } } mac[mac_len++] = val; if (*endptr == '\0') { if ((mac_len == 6) && (counter == 5)) { break; } else { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Add command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } } endptr++; } mcsAddCpeMacAddr(&(mac[0]), &result); if (result == MCS_SUCCESS) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n New Mac Address Added\n");CHECK_SNPRINTF(prntRtrn, len); } else if (result == MCS_FAILURE) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Could not add the Mac Address\n");CHECK_SNPRINTF(prntRtrn, len); } goto MCSACTION_read_proc_end; } else if (strncmp(g_proc_mcsAction_argv[0], "Del", strlen("Del")) == 0) { unsigned int mac_len = 0; Int8 *endptr; Uint8 counter = 0; if (argc != 2) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect number of parameters for Del command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } endptr = g_proc_mcsAction_argv[1]; /* Copy the MAC Address */ while (True) { Uint8 val; val = (Uint8)simple_strtol(endptr, (char**)&endptr, 16); if ((*endptr != ':') && (*endptr != '\0')) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Del command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } else if (*endptr == ':') { counter++; if ((*(endptr + 1)) == '\0') { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Del command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } } mac[mac_len++] = val; if (*endptr == '\0') { if ((mac_len == 6) && (counter == 5)) { break; } else { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Incorrect parameter for Del command\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } } endptr++; } mcsDelCpeMacAddr(&(mac[0]), &result); if (result == MCS_SUCCESS) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n Mac Address Deleted \n");CHECK_SNPRINTF(prntRtrn, len); } else if (result == MCS_FAILURE) { prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\nERROR: Could not Delete the Mac Address\n");CHECK_SNPRINTF(prntRtrn, len); } goto MCSACTION_read_proc_end; } else if (strncmp(g_proc_mcsAction_argv[0], "Print", strlen("Print")) == 0) { if (*ppos == 0) { endOfData = 0; } if (!printAction && !getSatisticsAction) { /* we can Print if we are already in Print Action */ printAction = 1; findMarkedMce (&num_entries, MCE_list ); } while (mceIndex < num_entries) { /* Get the VPID statistics. */ getMceSatistics (MCE_list[mceIndex]); /* Print the statistics on the console. */ prntRtrn = snprintf(buff+len, BUFF_FREE( len), "%02X:%02X:%02X:%02X:%02X:%02X|", MCE_list[mceIndex]->macAddress[0], MCE_list[mceIndex]->macAddress[1], MCE_list[mceIndex]->macAddress[2], MCE_list[mceIndex]->macAddress[3], MCE_list[mceIndex]->macAddress[4], MCE_list[mceIndex]->macAddress[5]);CHECK_SNPRINTF(prntRtrn, len); prntRtrn = snprintf(buff+len, BUFF_FREE( len), "%u|", DSPacketCount);CHECK_SNPRINTF(prntRtrn, len); prntRtrn = snprintf(buff+len, BUFF_FREE( len), "%llu|", DSByteCount);CHECK_SNPRINTF(prntRtrn, len); prntRtrn = snprintf(buff+len, BUFF_FREE( len), "%u|", USPacketCount);CHECK_SNPRINTF(prntRtrn, len); prntRtrn = snprintf(buff+len, BUFF_FREE( len), "%llu| \n", USByteCount);CHECK_SNPRINTF(prntRtrn, len); WR_TO_PAGE mceIndex++; *ppos += curr_off; /* Return number of bytes writen */ return curr_off ; } printAction = 0; endOfData = 0; mceIndex = 0; num_entries = 0; return MCS_SUCCESS; } else if (strncmp(g_proc_mcsAction_argv[0], "Flush", strlen("Flush")) == 0) { mcsFlushTable(&result); prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n MCS Flushed\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } else if (strncmp(g_proc_mcsAction_argv[0], "Dbg", strlen("Dbg")) == 0) { if (printAction || getSatisticsAction) { /* we can Print if we are already in Print Action */ prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n Still Process last Print or Dbg Commnad \n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } mcsPrintTable (&result); prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n Print Debug information \n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } else if (strncmp(g_proc_mcsAction_argv[0], "UnitT", strlen("UnitT")) == 0) { mcsBuildUnitTestTable(); prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n Build UnitTest Table\n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } else if (strncmp(g_proc_mcsAction_argv[0], "GetS", strlen("GetS")) == 0) { printMcsGetSatistics(); prntRtrn = snprintf(buff+len, BUFF_FREE(len), "\n Satisitics Function \n");CHECK_SNPRINTF(prntRtrn, len); goto MCSACTION_read_proc_end; } MCSACTION_read_proc_end: WR_TO_PAGE *ppos += curr_off; endOfData = 1; return curr_off; } /*=============================== Add Session Add / Del Functions ===========================*/ /************************************************************************** * FUNCTION NAME : mcsAddSessionInfo ************************************************************************** * DESCRIPTION : * Add the session information to the activeSessionList in the MCE * param[in] Session Handle * param[in] correlate MCE * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int mcsAddSessionInfo(Uint32 sessionHandle, macCountElement_T *matchMce) { Uint32 lockKey = 0; AVALANCHE_PP_SESSION_INFO_t *session_info; SESSION_DIRECTION direction = DIR_UNKNOWN; MCSCountSessionEntry_t *firstSession; if (avalanche_pp_session_get_info(sessionHandle, &session_info) != PP_RC_SUCCESS) { printk(KERN_DEBUG "mcsAddSessionInfo - could not get session %d info %d \n",sessionHandle); return MCS_FAILURE; } if (session_info->ingress.pid_type == AVALANCHE_PP_PID_TYPE_ETHERNET) // UPLINK { direction = DIR_US; } else if (session_info->ingress.pid_type == AVALANCHE_PP_PID_TYPE_DOCSIS) // Downlink { direction = DIR_DS; } firstSession = matchMce->activeSessionList; PAL_osProtectEntry(PAL_OSPROTECT_INTERRUPT, &lockKey); mac_counters_db.MCSSessionsTable[sessionHandle].sessionHandle = sessionHandle; mac_counters_db.MCSSessionsTable[sessionHandle].mcePtr = matchMce; mac_counters_db.MCSSessionsTable[sessionHandle].direction = direction; mac_counters_db.MCSSessionsTable[sessionHandle].nextSession = firstSession; mac_counters_db.MCSSessionsTable[sessionHandle].prvSession = NULL; // update the previous if(firstSession != NULL) { firstSession->prvSession = &(mac_counters_db.MCSSessionsTable[sessionHandle]); } matchMce->activeSessionList = &(mac_counters_db.MCSSessionsTable[sessionHandle]); PAL_osProtectExit(PAL_OSPROTECT_INTERRUPT, lockKey); return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcsAddSessionInfo ************************************************************************** * DESCRIPTION : * Add the session to the activeSessionList in the MCE * param[in] mac address * param[in] sessionHandle * param[in] result of operaton * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static void mcsAddSession (Uint8 *macAddr, Uint32 sessionHandle, int *result ) { int result1 = 0; macCountElement_T tmp; _macCountListEntry_T *tmp1 = NULL; // Find if this mac Address is valid in our MCS dataBase result1 = FindEntryByMacAddr (&(macAddr[0]), &tmp1); // if there is a place to enter it. if (result1 == MCS_FAILURE) // if this entry not valid { /* if there is MCS_LIST_SIZE marked by user entries , we can't enter new session */ if (numMarkedMCE == MCS_LIST_SIZE) { printk(KERN_DEBUG "if there is MCS_LIST_SIZE marked by user entries , we can't enter new session %d \n",sessionHandle); *result = MCS_FAILURE; return; } if ((numOfMCE == MCS_LIST_SIZE) && (numMarkedMCE < MCS_LIST_SIZE)) { *result = RemoveOldestMce(); if (*result == MCS_FAILURE) return MCS_FAILURE; } memcpy(&(tmp.macAddress[0]), &(macAddr[0]), 6); tmp.markedByUser = 0; tmp.activeSessionList = NULL; /* pointer to session list */ tmp.USPacketCount = 0; tmp.DSPacketCount = 0; tmp.USByteCount = 0; tmp.DSByteCount = 0; tmp.elementAge = jiffies; tmp1 = mcsAddMce (&tmp, tmp.markedByUser); // Add this element to the linked list } if(tmp1 != NULL) { *result = mcsAddSessionInfo(sessionHandle, &(tmp1->element)); } } /************************************************************************** * FUNCTION NAME : mcsAddSessionInfo ************************************************************************** * DESCRIPTION : * get Delete session notificaion * param[in] msessionHandle * param[in] sessionPackets * param[in] sessionBytes * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ static int mcsDelSession (unsigned int sessionHandle, unsigned int sessionPacketsFw, unsigned long long sessionOctetsFw) { MCSCountSessionEntry_t *currentSession = NULL; MCSCountSessionEntry_t *previousSession = NULL; MCSCountSessionEntry_t *nextSession = NULL; macCountElement_T* matchMce = (macCountElement_T*)(mac_counters_db.MCSSessionsTable[sessionHandle].mcePtr); if (sessionHandle >= AVALANCHE_PP_MAX_ACCELERATED_SESSIONS) { printk(KERN_DEBUG " sessionHandle Not Valid %d \n", sessionHandle); return MCS_FAILURE; } if (matchMce == NULL) { // This MCE does not exist anymore, only update the session table mac_counters_db.MCSSessionsTable[sessionHandle].mcePtr = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].nextSession = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].sessionHandle = 0; mac_counters_db.MCSSessionsTable[sessionHandle].direction= DIR_UNKNOWN; mac_counters_db.MCSSessionsTable[sessionHandle].prvSession = NULL; return MCS_SUCCESS; } /* update the Pointer of that sesion */ currentSession = &(mac_counters_db.MCSSessionsTable[sessionHandle]); if (currentSession == NULL) { printk (KERN_DEBUG " currentSession is null : sessionHandle is %d \n", sessionHandle); return MCS_FAILURE; } // if we got deleted session that we did not update before if ((currentSession->mcePtr == NULL) && (currentSession->sessionHandle == 0)) { printk (KERN_DEBUG " THIS IS SESSION we do not KNOW %d \n", sessionHandle); return MCS_FAILURE; } /* update the Satistics */ if (currentSession->direction == DIR_US) // UPLINK { matchMce->USPacketCount += sessionPacketsFw; matchMce->USByteCount += sessionOctetsFw; } else if (currentSession->direction == DIR_DS) // Downlink { matchMce->DSPacketCount += sessionPacketsFw; matchMce->DSByteCount += sessionOctetsFw; } /* update linked list */ MCSCountSessionEntry_t *activeSessionsList = (MCSCountSessionEntry_t *) matchMce->activeSessionList; if (activeSessionsList == NULL) { printk(KERN_DEBUG " Not with ActiveSessionList \n"); return MCS_FAILURE; } /* if need to remove the First Element */ if (activeSessionsList->sessionHandle == currentSession->sessionHandle) { /* if this the only element - check this to avoid get unreferenced pointer*/ if(mac_counters_db.MCSSessionsTable[sessionHandle].nextSession == NULL) { matchMce->activeSessionList = NULL; } else { matchMce->activeSessionList = currentSession->nextSession; } } else { if(mac_counters_db.MCSSessionsTable[sessionHandle].prvSession != NULL) { previousSession = (MCSCountSessionEntry_t *) currentSession->prvSession; } if(mac_counters_db.MCSSessionsTable[sessionHandle].nextSession!= NULL) { nextSession = (MCSCountSessionEntry_t *) currentSession->nextSession; } /* Element inside the list has previos and next */ if ((previousSession != NULL) && (nextSession != NULL)) { previousSession->nextSession = (MCSCountSessionEntry_t *) nextSession; nextSession->prvSession = (MCSCountSessionEntry_t *) previousSession; } /* If it is the last Element */ else if ((nextSession == NULL) && (previousSession != NULL)) { previousSession->nextSession = (MCSCountSessionEntry_t *) nextSession; } } mac_counters_db.MCSSessionsTable[sessionHandle].mcePtr = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].nextSession = NULL; mac_counters_db.MCSSessionsTable[sessionHandle].sessionHandle = 0; mac_counters_db.MCSSessionsTable[sessionHandle].direction= DIR_UNKNOWN; mac_counters_db.MCSSessionsTable[sessionHandle].prvSession = NULL; return MCS_SUCCESS; } /*=============================== Init Functions ===========================*/ static const struct file_operations mcsAction_proc_fops = { .read = MCSACTION_read_proc, .write = MCSACTION_write_proc }; static int mcsCtl_StartSessionNotification(unsigned int sessionHandle, struct sk_buff* skb) { int res = 0; #ifdef CONFIG_TI_PACKET_PROCESSOR_STATS if (skb) { if((skb->pp_packet_info.pp_session.ingress.pid_type == AVALANCHE_PP_PID_TYPE_DOCSIS) && (skb->pp_packet_info.pp_session.egress.pid_type == AVALANCHE_PP_PID_TYPE_ETHERNET)) // DS { if(&(skb->pp_packet_info.pp_session.egress.dstmac[0]) != NULL) { mcsAddSession (&(skb->pp_packet_info.pp_session.egress.dstmac[0]) , sessionHandle, &res); } } else if ((skb->pp_packet_info.pp_session.ingress.pid_type == AVALANCHE_PP_PID_TYPE_ETHERNET) && (skb->pp_packet_info.pp_session.egress.pid_type == AVALANCHE_PP_PID_TYPE_DOCSIS)) // US { if(&(skb->pp_packet_info.pp_session.ingress.lookup.LUT1.u.fields.L2.srcmac[0]) != NULL) { mcsAddSession (&(skb->pp_packet_info.pp_session.ingress.lookup.LUT1.u.fields.L2.srcmac[0]) , sessionHandle, &res); } } } #endif return res; } static int mcsCtl_DeleteSessionNotification(unsigned int sessionHandle, unsigned int sessionPacketsFw, unsigned long long sessionOctetsFw) { int res = 0; res = mcsDelSession(sessionHandle, sessionPacketsFw, sessionOctetsFw); return res; } /************************************************************************** * FUNCTION NAME : mcs_ctl_register_start_session_notification ************************************************************************** * DESCRIPTION : * Register the start session notification for mcs feature * callback function * * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcs_ctl_register_start_session_notification(MCS_START_SESSION mcs_start_session_notification) { if (mcs_ctl_start_session_notification_cb != NULL) { printk(KERN_DEBUG "Error: Mac Count element start session notification callback already exist\n"); return MCS_FAILURE; } mcs_ctl_start_session_notification_cb = mcs_start_session_notification; return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcs_ctl_unregister_start_session_notification ************************************************************************** * DESCRIPTION : * Un-Register start session notification for mac aging feature * callback function * * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcs_ctl_unregister_start_session_notification(void) { if (mcs_ctl_start_session_notification_cb == NULL) { printk(KERN_DEBUG "Error: Mac Count element start session notification callback empty\n"); return MCS_FAILURE; } mcs_ctl_start_session_notification_cb = NULL; return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcs_ctl_register_delete_session_notification ************************************************************************** * DESCRIPTION : * Register delete session notification for mac aging feature * callback function * * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcs_ctl_register_delete_session_notification(MCS_DELETE_SESSION mcs_delete_session_notification) { if (mcs_ctl_delete_session_notification_cb != NULL) { printk(KERN_DEBUG "Error: Mac Count element delete session notification callback already exist\n"); return MCS_FAILURE; } mcs_ctl_delete_session_notification_cb = mcs_delete_session_notification; return MCS_SUCCESS; } /************************************************************************** * FUNCTION NAME : mcs_ctl_unregister_delete_session_notification ************************************************************************** * DESCRIPTION : * Un-Register delete session notification for mac aging feature * callback function * * RETURNS : * 0 - Success * <0 - Error **************************************************************************/ int mcs_ctl_unregister_delete_session_notification(void) { if (mcs_ctl_delete_session_notification_cb == NULL) { printk(KERN_DEBUG "Error: Mac Count element delete session notification callback empty\n"); return MCS_FAILURE; } mcs_ctl_delete_session_notification_cb = NULL; return MCS_SUCCESS; } // end of declaration of register / unregister int mcsCountersCtl_Init(void) { memset((void *)&mac_counters_db, 0, sizeof(MCSCountersDataBase_t)); numOfMCE = 0; numMarkedMCE = 0; #ifdef CONFIG_TI_PACKET_PROCESSOR_STATS if (mcs_ctl_register_start_session_notification(mcsCtl_StartSessionNotification)) { printk(KERN_ERR"\n%s: Failed to register MCS start session notification callback in HIL\n", __FUNCTION__); return MCS_FAILURE; } if (mcs_ctl_register_delete_session_notification(mcsCtl_DeleteSessionNotification)) { printk(KERN_ERR"\n%s: Failed to register MCS start session notification callback in HIL\n", __FUNCTION__); return MCS_FAILURE; } #endif printk(KERN_INFO"\n MCS control init done\n"); return MCS_SUCCESS; } static int create_mcs_counters_cdev(void) { /* Allocate major and minor numbers for the device */ if (alloc_chrdev_region(&mcs_dev_numbers, MCS_CDEV_MIN_MINOR, MCS_CDEV_NUM_DEVICES, MCS_CDEV_NAME)) { printk(KERN_WARNING"\n%s: Failed to allocate Mac Count Satistics char device numbers\n", __FUNCTION__); return -ENODEV; } /* Allocate the device */ mcs_cdev = cdev_alloc(); if (!mcs_cdev) { printk(KERN_WARNING"\n%s: Failed to allocate Mac Count Satistics char device\n", __FUNCTION__); unregister_chrdev_region(mcs_dev_numbers, MCS_CDEV_NUM_DEVICES); return -ENOMEM; } /* Init device structure */ mcs_cdev->ops = &mcs_cdev_fops; mcs_cdev->owner = THIS_MODULE; /* Add the device to the kernel */ if (cdev_add(mcs_cdev, mcs_dev_numbers, MCS_CDEV_NUM_DEVICES)) { printk(KERN_WARNING"\n%s: Failed to add Mac Count Satistics char device\n", __FUNCTION__); kfree(mcs_cdev); unregister_chrdev_region(mcs_dev_numbers, MCS_CDEV_NUM_DEVICES); return -ENODEV; } return MCS_SUCCESS; } static int __init __module_mcs_init (void) { /* create base directory for or mcs (Mac Count Satistics) */ mcsctl = proc_mkdir("mcs_pp", init_net.proc_net); if (!mcsctl) { pr_err("Unable to proc dir entry\n"); remove_proc_entry("mcs_pp", init_net.proc_net); return -ENOMEM; } dir_mcsbase = proc_create("mcsAction" ,0644, mcsctl, &mcsAction_proc_fops); /* ************************************************************************ */ /* */ /* Interface device initialization stuff .... */ /* */ /* ************************************************************************ */ printk(KERN_DEBUG " MODULE: MCS Start ...\n"); create_mcs_counters_cdev(); mcsCountersCtl_Init(); return MCS_SUCCESS; } static void __module_mcs_exit (void) { printk(KERN_INFO " MODULE: MCS Stop ...\n"); cdev_del(mcs_cdev); unregister_chrdev_region(mcs_dev_numbers, MCS_CDEV_NUM_DEVICES); } module_init(__module_mcs_init); module_exit(__module_mcs_exit);