Back to home page

OSCL-LXR

 
 

    


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