Back to home page

LXR

 
 

    


0001 /******************************************************************************
0002  *
0003  *  (C)Copyright 1998,1999 SysKonnect,
0004  *  a business unit of Schneider & Koch & Co. Datensysteme GmbH.
0005  *
0006  *  See the file "skfddi.c" for further information.
0007  *
0008  *  This program is free software; you can redistribute it and/or modify
0009  *  it under the terms of the GNU General Public License as published by
0010  *  the Free Software Foundation; either version 2 of the License, or
0011  *  (at your option) any later version.
0012  *
0013  *  The information in this file is provided "AS IS" without warranty.
0014  *
0015  ******************************************************************************/
0016 
0017 /*
0018     SMT 7.2 Status Response Frame Implementation
0019     SRF state machine and frame generation
0020 */
0021 
0022 #include "h/types.h"
0023 #include "h/fddi.h"
0024 #include "h/smc.h"
0025 #include "h/smt_p.h"
0026 
0027 #define KERNEL
0028 #include "h/smtstate.h"
0029 
0030 #ifndef SLIM_SMT
0031 #ifndef BOOT
0032 
0033 #ifndef lint
0034 static const char ID_sccs[] = "@(#)srf.c    1.18 97/08/04 (C) SK " ;
0035 #endif
0036 
0037 
0038 /*
0039  * function declarations
0040  */
0041 static void clear_all_rep(struct s_smc *smc);
0042 static void clear_reported(struct s_smc *smc);
0043 static void smt_send_srf(struct s_smc *smc);
0044 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index);
0045 
0046 #define MAX_EVCS    ARRAY_SIZE(smc->evcs)
0047 
0048 struct evc_init {
0049     u_char code ;
0050     u_char index ;
0051     u_char n ;
0052     u_short para ;
0053 }  ;
0054 
0055 static const struct evc_init evc_inits[] = {
0056     { SMT_COND_SMT_PEER_WRAP,       0,1,SMT_P1048   } ,
0057 
0058     { SMT_COND_MAC_DUP_ADDR,        INDEX_MAC, NUMMACS,SMT_P208C } ,
0059     { SMT_COND_MAC_FRAME_ERROR,     INDEX_MAC, NUMMACS,SMT_P208D } ,
0060     { SMT_COND_MAC_NOT_COPIED,      INDEX_MAC, NUMMACS,SMT_P208E } ,
0061     { SMT_EVENT_MAC_NEIGHBOR_CHANGE,    INDEX_MAC, NUMMACS,SMT_P208F } ,
0062     { SMT_EVENT_MAC_PATH_CHANGE,        INDEX_MAC, NUMMACS,SMT_P2090 } ,
0063 
0064     { SMT_COND_PORT_LER,            INDEX_PORT,NUMPHYS,SMT_P4050 } ,
0065     { SMT_COND_PORT_EB_ERROR,       INDEX_PORT,NUMPHYS,SMT_P4052 } ,
0066     { SMT_EVENT_PORT_CONNECTION,        INDEX_PORT,NUMPHYS,SMT_P4051 } ,
0067     { SMT_EVENT_PORT_PATH_CHANGE,       INDEX_PORT,NUMPHYS,SMT_P4053 } ,
0068 } ;
0069 
0070 #define MAX_INIT_EVC    ARRAY_SIZE(evc_inits)
0071 
0072 void smt_init_evc(struct s_smc *smc)
0073 {
0074     struct s_srf_evc    *evc ;
0075     const struct evc_init   *init ;
0076     unsigned int        i ;
0077     int         index ;
0078     int         offset ;
0079 
0080     static u_char       fail_safe = FALSE ;
0081 
0082     memset((char *)smc->evcs,0,sizeof(smc->evcs)) ;
0083 
0084     evc = smc->evcs ;
0085     init = evc_inits ;
0086 
0087     for (i = 0 ; i < MAX_INIT_EVC ; i++) {
0088         for (index = 0 ; index < init->n ; index++) {
0089             evc->evc_code = init->code ;
0090             evc->evc_para = init->para ;
0091             evc->evc_index = init->index + index ;
0092 #ifndef DEBUG
0093             evc->evc_multiple = &fail_safe ;
0094             evc->evc_cond_state = &fail_safe ;
0095 #endif
0096             evc++ ;
0097         }
0098         init++ ;
0099     }
0100 
0101     if ((unsigned int) (evc - smc->evcs) > MAX_EVCS) {
0102         SMT_PANIC(smc,SMT_E0127, SMT_E0127_MSG) ;
0103     }
0104 
0105     /*
0106      * conditions
0107      */
0108     smc->evcs[0].evc_cond_state = &smc->mib.fddiSMTPeerWrapFlag ;
0109     smc->evcs[1].evc_cond_state =
0110         &smc->mib.m[MAC0].fddiMACDuplicateAddressCond ;
0111     smc->evcs[2].evc_cond_state =
0112         &smc->mib.m[MAC0].fddiMACFrameErrorFlag ;
0113     smc->evcs[3].evc_cond_state =
0114         &smc->mib.m[MAC0].fddiMACNotCopiedFlag ;
0115 
0116     /*
0117      * events
0118      */
0119     smc->evcs[4].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_N ;
0120     smc->evcs[5].evc_multiple = &smc->mib.m[MAC0].fddiMACMultiple_P ;
0121 
0122     offset = 6 ;
0123     for (i = 0 ; i < NUMPHYS ; i++) {
0124         /*
0125          * conditions
0126          */
0127         smc->evcs[offset + 0*NUMPHYS].evc_cond_state =
0128             &smc->mib.p[i].fddiPORTLerFlag ;
0129         smc->evcs[offset + 1*NUMPHYS].evc_cond_state =
0130             &smc->mib.p[i].fddiPORTEB_Condition ;
0131 
0132         /*
0133          * events
0134          */
0135         smc->evcs[offset + 2*NUMPHYS].evc_multiple =
0136             &smc->mib.p[i].fddiPORTMultiple_U ;
0137         smc->evcs[offset + 3*NUMPHYS].evc_multiple =
0138             &smc->mib.p[i].fddiPORTMultiple_P ;
0139         offset++ ;
0140     }
0141 #ifdef  DEBUG
0142     for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
0143         if (SMT_IS_CONDITION(evc->evc_code)) {
0144             if (!evc->evc_cond_state) {
0145                 SMT_PANIC(smc,SMT_E0128, SMT_E0128_MSG) ;
0146             }
0147             evc->evc_multiple = &fail_safe ;
0148         }
0149         else {
0150             if (!evc->evc_multiple) {
0151                 SMT_PANIC(smc,SMT_E0129, SMT_E0129_MSG) ;
0152             }
0153             evc->evc_cond_state = &fail_safe ;
0154         }
0155     }
0156 #endif
0157     smc->srf.TSR = smt_get_time() ;
0158     smc->srf.sr_state = SR0_WAIT ;
0159 }
0160 
0161 static struct s_srf_evc *smt_get_evc(struct s_smc *smc, int code, int index)
0162 {
0163     unsigned int        i ;
0164     struct s_srf_evc    *evc ;
0165 
0166     for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
0167         if (evc->evc_code == code && evc->evc_index == index)
0168             return evc;
0169     }
0170     return NULL;
0171 }
0172 
0173 #define THRESHOLD_2 (2*TICKS_PER_SECOND)
0174 #define THRESHOLD_32    (32*TICKS_PER_SECOND)
0175 
0176 #ifdef  DEBUG
0177 static const char * const srf_names[] = {
0178     "None","MACPathChangeEvent",    "MACNeighborChangeEvent",
0179     "PORTPathChangeEvent",      "PORTUndesiredConnectionAttemptEvent",
0180     "SMTPeerWrapCondition",     "SMTHoldCondition",
0181     "MACFrameErrorCondition",   "MACDuplicateAddressCondition",
0182     "MACNotCopiedCondition",    "PORTEBErrorCondition",
0183     "PORTLerCondition"
0184 } ;
0185 #endif
0186 
0187 void smt_srf_event(struct s_smc *smc, int code, int index, int cond)
0188 {
0189     struct s_srf_evc    *evc ;
0190     int         cond_asserted = 0 ;
0191     int         cond_deasserted = 0 ;
0192     int         event_occurred = 0 ;
0193     int         tsr ;
0194     int         T_Limit = 2*TICKS_PER_SECOND ;
0195 
0196     if (code == SMT_COND_MAC_DUP_ADDR && cond) {
0197         RS_SET(smc,RS_DUPADDR) ;
0198     }
0199 
0200     if (code) {
0201         DB_SMT("SRF: %s index %d\n",srf_names[code],index) ;
0202 
0203         if (!(evc = smt_get_evc(smc,code,index))) {
0204             DB_SMT("SRF : smt_get_evc() failed\n",0,0) ;
0205             return ;
0206         }
0207         /*
0208          * ignore condition if no change
0209          */
0210         if (SMT_IS_CONDITION(code)) {
0211             if (*evc->evc_cond_state == cond)
0212                 return ;
0213         }
0214 
0215         /*
0216          * set transition time stamp
0217          */
0218         smt_set_timestamp(smc,smc->mib.fddiSMTTransitionTimeStamp) ;
0219         if (SMT_IS_CONDITION(code)) {
0220             DB_SMT("SRF: condition is %s\n",cond ? "ON":"OFF",0) ;
0221             if (cond) {
0222                 *evc->evc_cond_state = TRUE ;
0223                 evc->evc_rep_required = TRUE ;
0224                 smc->srf.any_report = TRUE ;
0225                 cond_asserted = TRUE ;
0226             }
0227             else {
0228                 *evc->evc_cond_state = FALSE ;
0229                 cond_deasserted = TRUE ;
0230             }
0231         }
0232         else {
0233             if (evc->evc_rep_required) {
0234                 *evc->evc_multiple  = TRUE ;
0235             }
0236             else {
0237                 evc->evc_rep_required = TRUE ;
0238                 *evc->evc_multiple  = FALSE ;
0239             }
0240             smc->srf.any_report = TRUE ;
0241             event_occurred = TRUE ;
0242         }
0243 #ifdef  FDDI_MIB
0244         snmp_srf_event(smc,evc) ;
0245 #endif  /* FDDI_MIB */
0246     }
0247     tsr = smt_get_time() - smc->srf.TSR ;
0248 
0249     switch (smc->srf.sr_state) {
0250     case SR0_WAIT :
0251         /* SR01a */
0252         if (cond_asserted && tsr < T_Limit) {
0253             smc->srf.SRThreshold = THRESHOLD_2 ;
0254             smc->srf.sr_state = SR1_HOLDOFF ;
0255             break ;
0256         }
0257         /* SR01b */
0258         if (cond_deasserted && tsr < T_Limit) {
0259             smc->srf.sr_state = SR1_HOLDOFF ;
0260             break ;
0261         }
0262         /* SR01c */
0263         if (event_occurred && tsr < T_Limit) {
0264             smc->srf.sr_state = SR1_HOLDOFF ;
0265             break ;
0266         }
0267         /* SR00b */
0268         if (cond_asserted && tsr >= T_Limit) {
0269             smc->srf.SRThreshold = THRESHOLD_2 ;
0270             smc->srf.TSR = smt_get_time() ;
0271             smt_send_srf(smc) ;
0272             break ;
0273         }
0274         /* SR00c */
0275         if (cond_deasserted && tsr >= T_Limit) {
0276             smc->srf.TSR = smt_get_time() ;
0277             smt_send_srf(smc) ;
0278             break ;
0279         }
0280         /* SR00d */
0281         if (event_occurred && tsr >= T_Limit) {
0282             smc->srf.TSR = smt_get_time() ;
0283             smt_send_srf(smc) ;
0284             break ;
0285         }
0286         /* SR00e */
0287         if (smc->srf.any_report && (u_long) tsr >=
0288             smc->srf.SRThreshold) {
0289             smc->srf.SRThreshold *= 2 ;
0290             if (smc->srf.SRThreshold > THRESHOLD_32)
0291                 smc->srf.SRThreshold = THRESHOLD_32 ;
0292             smc->srf.TSR = smt_get_time() ;
0293             smt_send_srf(smc) ;
0294             break ;
0295         }
0296         /* SR02 */
0297         if (!smc->mib.fddiSMTStatRptPolicy) {
0298             smc->srf.sr_state = SR2_DISABLED ;
0299             break ;
0300         }
0301         break ;
0302     case SR1_HOLDOFF :
0303         /* SR10b */
0304         if (tsr >= T_Limit) {
0305             smc->srf.sr_state = SR0_WAIT ;
0306             smc->srf.TSR = smt_get_time() ;
0307             smt_send_srf(smc) ;
0308             break ;
0309         }
0310         /* SR11a */
0311         if (cond_asserted) {
0312             smc->srf.SRThreshold = THRESHOLD_2 ;
0313         }
0314         /* SR11b */
0315         /* SR11c */
0316         /* handled above */
0317         /* SR12 */
0318         if (!smc->mib.fddiSMTStatRptPolicy) {
0319             smc->srf.sr_state = SR2_DISABLED ;
0320             break ;
0321         }
0322         break ;
0323     case SR2_DISABLED :
0324         if (smc->mib.fddiSMTStatRptPolicy) {
0325             smc->srf.sr_state = SR0_WAIT ;
0326             smc->srf.TSR = smt_get_time() ;
0327             smc->srf.SRThreshold = THRESHOLD_2 ;
0328             clear_all_rep(smc) ;
0329             break ;
0330         }
0331         break ;
0332     }
0333 }
0334 
0335 static void clear_all_rep(struct s_smc *smc)
0336 {
0337     struct s_srf_evc    *evc ;
0338     unsigned int        i ;
0339 
0340     for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
0341         evc->evc_rep_required = FALSE ;
0342         if (SMT_IS_CONDITION(evc->evc_code))
0343             *evc->evc_cond_state = FALSE ;
0344     }
0345     smc->srf.any_report = FALSE ;
0346 }
0347 
0348 static void clear_reported(struct s_smc *smc)
0349 {
0350     struct s_srf_evc    *evc ;
0351     unsigned int        i ;
0352 
0353     smc->srf.any_report = FALSE ;
0354     for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
0355         if (SMT_IS_CONDITION(evc->evc_code)) {
0356             if (*evc->evc_cond_state == FALSE)
0357                 evc->evc_rep_required = FALSE ;
0358             else
0359                 smc->srf.any_report = TRUE ;
0360         }
0361         else {
0362             evc->evc_rep_required = FALSE ;
0363             *evc->evc_multiple = FALSE ;
0364         }
0365     }
0366 }
0367 
0368 /*
0369  * build and send SMT SRF frame
0370  */
0371 static void smt_send_srf(struct s_smc *smc)
0372 {
0373 
0374     struct smt_header   *smt ;
0375     struct s_srf_evc    *evc ;
0376     SK_LOC_DECL(struct s_pcon,pcon) ;
0377     SMbuf           *mb ;
0378     unsigned int        i ;
0379 
0380     static const struct fddi_addr SMT_SRF_DA = {
0381         { 0x80, 0x01, 0x43, 0x00, 0x80, 0x08 }
0382     } ;
0383 
0384     /*
0385      * build SMT header
0386      */
0387     if (!smc->r.sm_ma_avail)
0388         return ;
0389     if (!(mb = smt_build_frame(smc,SMT_SRF,SMT_ANNOUNCE,0)))
0390         return ;
0391 
0392     RS_SET(smc,RS_SOFTERROR) ;
0393 
0394     smt = smtod(mb, struct smt_header *) ;
0395     smt->smt_dest = SMT_SRF_DA ;        /* DA == SRF multicast */
0396 
0397     /*
0398      * setup parameter status
0399      */
0400     pcon.pc_len = SMT_MAX_INFO_LEN ;    /* max para length */
0401     pcon.pc_err = 0 ;           /* no error */
0402     pcon.pc_badset = 0 ;            /* no bad set count */
0403     pcon.pc_p = (void *) (smt + 1) ;    /* paras start here */
0404 
0405     smt_add_para(smc,&pcon,(u_short) SMT_P1033,0,0) ;
0406     smt_add_para(smc,&pcon,(u_short) SMT_P1034,0,0) ;
0407 
0408     for (i = 0, evc = smc->evcs ; i < MAX_EVCS ; i++, evc++) {
0409         if (evc->evc_rep_required) {
0410             smt_add_para(smc,&pcon,evc->evc_para,
0411                 (int)evc->evc_index,0) ;
0412         }
0413     }
0414     smt->smt_len = SMT_MAX_INFO_LEN - pcon.pc_len ;
0415     mb->sm_len = smt->smt_len + sizeof(struct smt_header) ;
0416 
0417     DB_SMT("SRF: sending SRF at %p, len %d\n",smt,mb->sm_len) ;
0418     DB_SMT("SRF: state SR%d Threshold %d\n",
0419         smc->srf.sr_state,smc->srf.SRThreshold/TICKS_PER_SECOND) ;
0420 #ifdef  DEBUG
0421     dump_smt(smc,smt,"SRF Send") ;
0422 #endif
0423     smt_send_frame(smc,mb,FC_SMT_INFO,0) ;
0424     clear_reported(smc) ;
0425 }
0426 
0427 #endif  /* no BOOT */
0428 #endif  /* no SLIM_SMT */
0429