1 /******************************************************************************
 
   3  *      (C)Copyright 1998,1999 SysKonnect,
 
   4  *      a business unit of Schneider & Koch & Co. Datensysteme GmbH.
 
   6  *      See the file "skfddi.c" for further information.
 
   8  *      This program is free software; you can redistribute it and/or modify
 
   9  *      it under the terms of the GNU General Public License as published by
 
  10  *      the Free Software Foundation; either version 2 of the License, or
 
  11  *      (at your option) any later version.
 
  13  *      The information in this file is provided "AS IS" without warranty.
 
  15  ******************************************************************************/
 
  18         SMT 7.2 Status Response Frame Implementation
 
  19         SRF state machine and frame generation
 
  28 #include "h/smtstate.h"
 
  34 static const char ID_sccs[] = "@(#)srf.c        1.18 97/08/04 (C) SK " ;
 
  39  * function declarations
 
  41 static void clear_all_rep(struct s_smc *smc);
 
  42 static void clear_reported(struct s_smc *smc);
 
  43 static void smt_send_srf(struct s_smc *smc);
 
  44 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
 
  46 #define MAX_EVCS        (sizeof(smc->evcs)/sizeof(smc->evcs[0]))
 
  55 static const struct evc_init evc_inits[] = {
 
  56         { SMT_COND_SMT_PEER_WRAP,               0,1,SMT_P1048   } ,
 
  58         { SMT_COND_MAC_DUP_ADDR,                INDEX_MAC, NUMMACS,SMT_P208C } ,
 
  59         { SMT_COND_MAC_FRAME_ERROR,             INDEX_MAC, NUMMACS,SMT_P208D } ,
 
  60         { SMT_COND_MAC_NOT_COPIED,              INDEX_MAC, NUMMACS,SMT_P208E } ,
 
  61         { SMT_EVENT_MAC_NEIGHBOR_CHANGE,        INDEX_MAC, NUMMACS,SMT_P208F } ,
 
  62         { SMT_EVENT_MAC_PATH_CHANGE,            INDEX_MAC, NUMMACS,SMT_P2090 } ,
 
  64         { SMT_COND_PORT_LER,                    INDEX_PORT,NUMPHYS,SMT_P4050 } ,
 
  65         { SMT_COND_PORT_EB_ERROR,               INDEX_PORT,NUMPHYS,SMT_P4052 } ,
 
  66         { SMT_EVENT_PORT_CONNECTION,            INDEX_PORT,NUMPHYS,SMT_P4051 } ,
 
  67         { SMT_EVENT_PORT_PATH_CHANGE,           INDEX_PORT,NUMPHYS,SMT_P4053 } ,
 
  70 #define MAX_INIT_EVC    (sizeof(evc_inits)/sizeof(evc_inits[0]))
 
  72 void smt_init_evc(struct s_smc *smc)
 
  74         struct s_srf_evc        *evc ;
 
  75         const struct evc_init   *init ;
 
  80         static u_char           fail_safe = FALSE ;
 
  82         memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
 
  87         for (i = 0 ; (unsigned) i < MAX_INIT_EVC ; i++) {
 
  88                 for (index = 0 ; index < init->n ; index++) {
 
  89                         evc->evc_code = init->code ;
 
  90                         evc->evc_para = init->para ;
 
  91                         evc->evc_index = init->index + index ;
 
  93                         evc->evc_multiple = &fail_safe ;
 
  94                         evc->evc_cond_state = &fail_safe ;
 
 101         if ((unsigned) (evc - smc->evcs) > MAX_EVCS) {
 
 102                 SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
 
 108         smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
 
 109         smc->evcs[1].evc_cond_state =
 
 110                 &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
 
 111         smc->evcs[2].evc_cond_state =
 
 112                 &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
 
 113         smc->evcs[3].evc_cond_state =
 
 114                 &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
 
 119         smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
 
 120         smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
 
 123         for (i = 0 ; i < NUMPHYS ; i++) {
 
 127                 smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
 
 128                         &smc->mib.p[i].fddiPORTLerFlag ;
 
 129                 smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
 
 130                         &smc->mib.p[i].fddiPORTEB_Condition ;
 
 135                 smc->evcs[offset + 2*NUMPHYS].evc_multiple =
 
 136                         &smc->mib.p[i].fddiPORTMultiple_U ;
 
 137                 smc->evcs[offset + 3*NUMPHYS].evc_multiple =
 
 138                         &smc->mib.p[i].fddiPORTMultiple_P ;
 
 142         for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 
 143                 if (SMT_IS_CONDITION(evc->evc_code)) {
 
 144                         if (!evc->evc_cond_state) {
 
 145                                 SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
 
 147                         evc->evc_multiple = &fail_safe ;
 
 150                         if (!evc->evc_multiple) {
 
 151                                 SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
 
 153                         evc->evc_cond_state = &fail_safe ;
 
 157         smc->srf.TSR = smt_get_time() ;
 
 158         smc->srf.sr_state = SR0_WAIT ;
 
 161 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
 
 164         struct s_srf_evc        *evc ;
 
 166         for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 
 167                 if (evc->evc_code == code && evc->evc_index == index)
 
 173 #define THRESHOLD_2     (2*TICKS_PER_SECOND)
 
 174 #define THRESHOLD_32    (32*TICKS_PER_SECOND)
 
 177 static const char * const srf_names[] = {
 
 178         "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
 
 179         "PORTPathChangeEvent",          "PORTUndesiredConnectionAttemptEvent",
 
 180         "SMTPeerWrapCondition",         "SMTHoldCondition",
 
 181         "MACFrameErrorCondition",       "MACDuplicateAddressCondition",
 
 182         "MACNotCopiedCondition",        "PORTEBErrorCondition",
 
 187 void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
 
 189         struct s_srf_evc        *evc ;
 
 190         int                     cond_asserted = 0 ;
 
 191         int                     cond_deasserted = 0 ;
 
 192         int                     event_occurred = 0 ;
 
 194         int                     T_Limit = 2*TICKS_PER_SECOND ;
 
 196         if (code == SMT_COND_MAC_DUP_ADDR && cond) {
 
 197                 RS_SET(smc,RS_DUPADDR) ;
 
 201                 DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
 
 203                 if (!(evc = smt_get_evc(smc,code,index))) {
 
 204                         DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
 
 208                  * ignore condition if no change
 
 210                 if (SMT_IS_CONDITION(code)) {
 
 211                         if (*evc->evc_cond_state == cond)
 
 216                  * set transition time stamp
 
 218                 smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
 
 219                 if (SMT_IS_CONDITION(code)) {
 
 220                         DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
 
 222                                 *evc->evc_cond_state = TRUE ;
 
 223                                 evc->evc_rep_required = TRUE ;
 
 224                                 smc->srf.any_report = TRUE ;
 
 225                                 cond_asserted = TRUE ;
 
 228                                 *evc->evc_cond_state = FALSE ;
 
 229                                 cond_deasserted = TRUE ;
 
 233                         if (evc->evc_rep_required) {
 
 234                                 *evc->evc_multiple  = TRUE ;
 
 237                                 evc->evc_rep_required = TRUE ;
 
 238                                 *evc->evc_multiple  = FALSE ;
 
 240                         smc->srf.any_report = TRUE ;
 
 241                         event_occurred = TRUE ;
 
 244                 snmp_srf_event(smc,evc) ;
 
 245 #endif  /* FDDI_MIB */
 
 247         tsr = smt_get_time() - smc->srf.TSR ;
 
 249         switch (smc->srf.sr_state) {
 
 252                 if (cond_asserted && tsr < T_Limit) {
 
 253                         smc->srf.SRThreshold = THRESHOLD_2 ;
 
 254                         smc->srf.sr_state = SR1_HOLDOFF ;
 
 258                 if (cond_deasserted && tsr < T_Limit) {
 
 259                         smc->srf.sr_state = SR1_HOLDOFF ;
 
 263                 if (event_occurred && tsr < T_Limit) {
 
 264                         smc->srf.sr_state = SR1_HOLDOFF ;
 
 268                 if (cond_asserted && tsr >= T_Limit) {
 
 269                         smc->srf.SRThreshold = THRESHOLD_2 ;
 
 270                         smc->srf.TSR = smt_get_time() ;
 
 275                 if (cond_deasserted && tsr >= T_Limit) {
 
 276                         smc->srf.TSR = smt_get_time() ;
 
 281                 if (event_occurred && tsr >= T_Limit) {
 
 282                         smc->srf.TSR = smt_get_time() ;
 
 287                 if (smc->srf.any_report && (u_long) tsr >=
 
 288                         smc->srf.SRThreshold) {
 
 289                         smc->srf.SRThreshold *= 2 ;
 
 290                         if (smc->srf.SRThreshold > THRESHOLD_32)
 
 291                                 smc->srf.SRThreshold = THRESHOLD_32 ;
 
 292                         smc->srf.TSR = smt_get_time() ;
 
 297                 if (!smc->mib.fddiSMTStatRptPolicy) {
 
 298                         smc->srf.sr_state = SR2_DISABLED ;
 
 304                 if (tsr >= T_Limit) {
 
 305                         smc->srf.sr_state = SR0_WAIT ;
 
 306                         smc->srf.TSR = smt_get_time() ;
 
 312                         smc->srf.SRThreshold = THRESHOLD_2 ;
 
 318                 if (!smc->mib.fddiSMTStatRptPolicy) {
 
 319                         smc->srf.sr_state = SR2_DISABLED ;
 
 324                 if (smc->mib.fddiSMTStatRptPolicy) {
 
 325                         smc->srf.sr_state = SR0_WAIT ;
 
 326                         smc->srf.TSR = smt_get_time() ;
 
 327                         smc->srf.SRThreshold = THRESHOLD_2 ;
 
 335 static void clear_all_rep(struct s_smc *smc)
 
 337         struct s_srf_evc        *evc ;
 
 340         for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 
 341                 evc->evc_rep_required = FALSE ;
 
 342                 if (SMT_IS_CONDITION(evc->evc_code))
 
 343                         *evc->evc_cond_state = FALSE ;
 
 345         smc->srf.any_report = FALSE ;
 
 348 static void clear_reported(struct s_smc *smc)
 
 350         struct s_srf_evc        *evc ;
 
 353         smc->srf.any_report = FALSE ;
 
 354         for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 
 355                 if (SMT_IS_CONDITION(evc->evc_code)) {
 
 356                         if (*evc->evc_cond_state == FALSE)
 
 357                                 evc->evc_rep_required = FALSE ;
 
 359                                 smc->srf.any_report = TRUE ;
 
 362                         evc->evc_rep_required = FALSE ;
 
 363                         *evc->evc_multiple = FALSE ;
 
 369  * build and send SMT SRF frame
 
 371 static void smt_send_srf(struct s_smc *smc)
 
 374         struct smt_header       *smt ;
 
 375         struct s_srf_evc        *evc ;
 
 376         SK_LOC_DECL(struct s_pcon,pcon) ;
 
 380         static const struct fddi_addr SMT_SRF_DA = {
 
 381                 { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
 
 387         if (!smc->r.sm_ma_avail)
 
 389         if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
 
 392         RS_SET(smc,RS_SOFTERROR) ;
 
 394         smt = smtod(mb, struct smt_header *) ;
 
 395         smt->smt_dest = SMT_SRF_DA ;            /* DA == SRF multicast */
 
 398          * setup parameter status
 
 400         pcon.pc_len = SMT_MAX_INFO_LEN ;        /* max para length */
 
 401         pcon.pc_err = 0 ;                       /* no error */
 
 402         pcon.pc_badset = 0 ;                    /* no bad set count */
 
 403         pcon.pc_p = (void *) (smt + 1) ;        /* paras start here */
 
 405         smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
 
 406         smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
 
 408         for (i = 0, evc = smc->evcs ; (unsigned) i < MAX_EVCS ; i++, evc++) {
 
 409                 if (evc->evc_rep_required) {
 
 410                         smt_add_para(smc,&pcon,evc->evc_para,
 
 411                                 (int)evc->evc_index,0) ;
 
 414         smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
 
 415         mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
 
 417         DB_SMT("SRF: sending SRF at %x, len %d \n",smt,mb->sm_len) ;
 
 418         DB_SMT("SRF: state SR%d Threshold %d\n",
 
 419                 smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
 
 421         dump_smt(smc,smt,"SRF Send") ;
 
 423         smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
 
 424         clear_reported(smc) ;
 
 428 #endif  /* no SLIM_SMT */