char *mrp_print_status(const mrp_applicant_attribute_t * app, const mrp_registrar_attribute_t * reg) { /* * output looks like VO->AA/IN->MT, or QA/IN */ if ((app->mrp_state == app->mrp_previous_state) && (reg->mrp_state == reg->mrp_previous_state)) { snprintf(state_status_string, sizeof(state_status_string) - 1, "%s/%s", mrp_state_string(app->mrp_state), mrp_state_string(reg->mrp_state)); } else if ((app->mrp_state != app->mrp_previous_state) && (reg->mrp_state == reg->mrp_previous_state)) { snprintf(state_status_string, sizeof(state_status_string) - 1, "%s->%s/%s", mrp_state_string(app->mrp_previous_state), mrp_state_string(app->mrp_state), mrp_state_string(reg->mrp_state)); } else if ((app->mrp_state == app->mrp_previous_state) && (reg->mrp_state != reg->mrp_previous_state)) { snprintf(state_status_string, sizeof(state_status_string) - 1, "%s/%s->%s", mrp_state_string(app->mrp_state), mrp_state_string(reg->mrp_previous_state), mrp_state_string(reg->mrp_state)); } else if ((app->mrp_state != app->mrp_previous_state) && (reg->mrp_state != reg->mrp_previous_state)) { snprintf(state_status_string, sizeof(state_status_string) - 1, "%s->%s/%s->%s", mrp_state_string(app->mrp_previous_state), mrp_state_string(app->mrp_state), mrp_state_string(reg->mrp_previous_state), mrp_state_string(reg->mrp_state)); } return state_status_string; }
int mrp_registrar_fsm(mrp_registrar_attribute_t * attrib, struct mrp_database *mrp_db, int event) { int mrp_state = attrib->mrp_state; int notify = MRP_NOTIFY_NONE; switch (event) { case MRP_EVENT_BEGIN: mrp_state = MRP_MT_STATE; break; case MRP_EVENT_RLV: notify = MRP_NOTIFY_LV; /* fall thru */ case MRP_EVENT_TXLA: case MRP_EVENT_RLA: case MRP_EVENT_REDECLARE: /* * on link-status-change * trigger Applicant and Registrar state machines to re-declare * previously registered attributes. */ switch (mrp_state) { case MRP_IN_STATE: mrp_lvtimer_start(mrp_db); mrp_state = MRP_LV_STATE; default: break; } break; case MRP_EVENT_RNEW: notify = MRP_NOTIFY_NEW; switch (mrp_state) { case MRP_MT_STATE: case MRP_IN_STATE: mrp_state = MRP_IN_STATE; break; case MRP_LV_STATE: /* should stop leavetimer - but we have only 1 lvtimer * for all attributes, and recieving a LVTIMER event * is a don't-care if the attribute is in the IN state. */ mrp_state = MRP_IN_STATE; break; default: break; } break; case MRP_EVENT_RJOININ: case MRP_EVENT_RJOINMT: switch (mrp_state) { case MRP_MT_STATE: notify = MRP_NOTIFY_JOIN; mrp_state = MRP_IN_STATE; break; case MRP_IN_STATE: mrp_state = MRP_IN_STATE; break; case MRP_LV_STATE: /* should stop leavetimer - but we have only 1 lvtimer * for all attributes, and receiving a LVTIMER event * is a don't-care if the attribute is in the IN state. */ notify = MRP_NOTIFY_JOIN; mrp_state = MRP_IN_STATE; break; default: break; } break; case MRP_EVENT_LVTIMER: switch (mrp_state) { case MRP_LV_STATE: notify = MRP_NOTIFY_LV; mrp_state = MRP_MT_STATE; break; case MRP_MT_STATE: mrp_state = MRP_MT_STATE; break; case MRP_IN_STATE: default: break; } break; case MRP_EVENT_FLUSH: notify = MRP_NOTIFY_LV; switch (mrp_state) { case MRP_LV_STATE: mrp_state = MRP_MT_STATE; break; case MRP_MT_STATE: case MRP_IN_STATE: mrp_state = MRP_MT_STATE; break; default: break; } break; case MRP_EVENT_RMT: /* ignore on soon to be deleted attributes */ break; case MRP_EVENT_RIN: /* rIn! event processing is not specified in section 10.7.8 of IEEE802.1Q-2011, * table 10.4, so ignore it here. */ break; default: #if LOG_MVRP || LOG_MSRP || LOG_MMRP || LOG_MRP printf("mrp_registrar_fsm:unexpected event %s (%d), state %s\n", mrp_event_string(event), event, mrp_state_string(mrp_state)); #endif return -1; break; } #if LOG_MRP attrib->mrp_previous_state = attrib->mrp_state; #endif attrib->mrp_state = mrp_state; attrib->notify = notify; return 0; }
int mrp_applicant_fsm(struct mrp_database *mrp_db, mrp_applicant_attribute_t * attrib, int event) { int tx = 0; int optional = 0; int mrp_state = attrib->mrp_state; int sndmsg = MRP_SND_NULL; (void)mrp_db; switch (event) { case MRP_EVENT_BEGIN: mrp_state = MRP_VO_STATE; break; case MRP_EVENT_NEW: /* * New declaration (publish) event as a result * of a mad_join request */ switch (mrp_state) { case MRP_VN_STATE: case MRP_AN_STATE: /* do nothing */ break; default: mrp_state = MRP_VN_STATE; break; } break; case MRP_EVENT_JOIN: /* * declaration (of interest) event as a result of * a mad_join request */ switch (mrp_state) { case MRP_LO_STATE: case MRP_VO_STATE: mrp_state = MRP_VP_STATE; break; case MRP_LA_STATE: mrp_state = MRP_AA_STATE; break; case MRP_AO_STATE: mrp_state = MRP_AP_STATE; break; case MRP_QO_STATE: mrp_state = MRP_QP_STATE; break; default: break; } break; case MRP_EVENT_LV: /* * declaration removal event as a result of a mad_leave request */ switch (mrp_state) { case MRP_VN_STATE: case MRP_AN_STATE: case MRP_AA_STATE: case MRP_QA_STATE: mrp_state = MRP_LA_STATE; break; case MRP_VP_STATE: mrp_state = MRP_VO_STATE; break; case MRP_AP_STATE: mrp_state = MRP_AO_STATE; break; case MRP_QP_STATE: mrp_state = MRP_QO_STATE; break; default: break; } break; case MRP_EVENT_TXLA: /* * transmit leaveall is signaled (overrides a TX) */ switch (mrp_state) { case MRP_VO_STATE: /* send <NULL> only if it improves encoding */ optional = 1; tx = 1; sndmsg = MRP_SND_IN; mrp_state = MRP_LO_STATE; break; case MRP_VP_STATE: tx = 1; sndmsg = MRP_SND_IN; mrp_state = MRP_AA_STATE; break; case MRP_VN_STATE: /* send NEW */ tx = 1; sndmsg = MRP_SND_NEW; mrp_state = MRP_AN_STATE; break; case MRP_AN_STATE: /* send NEW */ tx = 1; sndmsg = MRP_SND_NEW; mrp_state = MRP_QA_STATE; break; case MRP_QP_STATE: case MRP_AP_STATE: case MRP_AA_STATE: /* send JOIN */ tx = 1; sndmsg = MRP_SND_JOIN; mrp_state = MRP_QA_STATE; break; case MRP_QA_STATE: /* send JOIN */ tx = 1; sndmsg = MRP_SND_JOIN; break; case MRP_LA_STATE: case MRP_AO_STATE: case MRP_QO_STATE: /* send <NULL> only if it improves encoding */ optional = 1; tx = 1; sndmsg = MRP_SND_IN; mrp_state = MRP_LO_STATE; break; case MRP_LO_STATE: /* send <NULL> */ optional = 1; tx = 1; sndmsg = MRP_SND_IN; mrp_state = MRP_VO_STATE; break; default: break; } break; case MRP_EVENT_TXLAF: /* * transmit leaveall failure (no room) */ switch (mrp_state) { case MRP_VO_STATE: mrp_state = MRP_LO_STATE; break; case MRP_LO_STATE: case MRP_VP_STATE: case MRP_VN_STATE: /* don't advance state */ break; case MRP_AN_STATE: mrp_state = MRP_VN_STATE; break; case MRP_QP_STATE: case MRP_AP_STATE: case MRP_AA_STATE: case MRP_QA_STATE: mrp_state = MRP_VP_STATE; break; case MRP_QO_STATE: case MRP_AO_STATE: case MRP_LA_STATE: mrp_state = MRP_LO_STATE; break; default: break; } break; case MRP_EVENT_TX: /* * transmit updates unless leaveall is signaled * (then it becomes a TXLA) */ switch (mrp_state) { case MRP_VO_STATE: /* send <NULL> only if it improves encoding */ tx = 1; optional = 1; sndmsg = MRP_SND_IN; break; case MRP_VP_STATE: /* send JOIN */ tx = 1; sndmsg = MRP_SND_JOIN; mrp_state = MRP_AA_STATE; break; case MRP_VN_STATE: /* send NEW */ tx = 1; sndmsg = MRP_SND_NEW; mrp_state = MRP_AN_STATE; break; case MRP_AN_STATE: /* send NEW */ tx = 1; sndmsg = MRP_SND_NEW; mrp_state = MRP_QA_STATE; break; case MRP_AP_STATE: case MRP_AA_STATE: /* send JOIN */ tx = 1; sndmsg = MRP_SND_JOIN; mrp_state = MRP_QA_STATE; break; case MRP_QA_STATE: /* send JOIN only if it improves encoding */ tx = 1; optional = 1; sndmsg = MRP_SND_JOIN; break; case MRP_LA_STATE: /* send LV */ tx = 1; sndmsg = MRP_SND_LV; mrp_state = MRP_VO_STATE; break; case MRP_AO_STATE: case MRP_QO_STATE: case MRP_QP_STATE: /* send <NULL> only if it improves encoding */ tx = 1; optional = 1; sndmsg = MRP_SND_IN; break; case MRP_LO_STATE: /* send <NULL> */ tx = 1; sndmsg = MRP_SND_IN; mrp_state = MRP_VO_STATE; break; default: break; } break; case MRP_EVENT_RNEW: /* do nothing */ break; case MRP_EVENT_RJOININ: switch (mrp_state) { case MRP_VO_STATE: if (0 == p2pmac) mrp_state = MRP_AO_STATE; break; case MRP_VP_STATE: if (0 == p2pmac) { mrp_state = MRP_AP_STATE; } break; case MRP_AA_STATE: mrp_state = MRP_QA_STATE; break; case MRP_AO_STATE: mrp_state = MRP_QO_STATE; break; case MRP_AP_STATE: mrp_state = MRP_QP_STATE; break; default: break; } break; case MRP_EVENT_RIN: switch (mrp_state) { case MRP_AA_STATE: if (1 == p2pmac) mrp_state = MRP_QA_STATE; break; default: break; } break; case MRP_EVENT_RJOINMT: case MRP_EVENT_RMT: switch (mrp_state) { case MRP_QA_STATE: mrp_state = MRP_AA_STATE; break; case MRP_QO_STATE: mrp_state = MRP_AO_STATE; break; case MRP_QP_STATE: mrp_state = MRP_AP_STATE; break; case MRP_LO_STATE: mrp_state = MRP_VO_STATE; break; default: break; } break; case MRP_EVENT_RLV: case MRP_EVENT_RLA: case MRP_EVENT_REDECLARE: switch (mrp_state) { case MRP_VO_STATE: mrp_state = MRP_LO_STATE; break; case MRP_AN_STATE: mrp_state = MRP_VN_STATE; break; case MRP_QA_STATE: case MRP_AA_STATE: mrp_state = MRP_VP_STATE; break; case MRP_AO_STATE: case MRP_QO_STATE: mrp_state = MRP_LO_STATE; break; case MRP_AP_STATE: case MRP_QP_STATE: mrp_state = MRP_VP_STATE; break; default: break; } break; case MRP_EVENT_PERIODIC: switch (mrp_state) { case MRP_QA_STATE: mrp_state = MRP_AA_STATE; break; case MRP_QP_STATE: mrp_state = MRP_AP_STATE; break; default: break; } break; default: printf("mrp_applicant_fsm:unexpected event %s (%d)\n", mrp_event_string(event), event); return -1; break; } attrib->tx = tx; #if LOG_MVRP || LOG_MSRP || LOG_MMRP if (attrib->mrp_state != mrp_state) { mrpd_log_printf("mrp_applicant_fsm event %s, state %s -> %s\n", mrp_event_string(event), mrp_state_string(attrib->mrp_state), mrp_state_string(mrp_state)); } else { mrpd_log_printf("mrp_applicant_fsm event %s, state %s\n", mrp_event_string(event), mrp_state_string(mrp_state)); } #endif attrib->mrp_state = mrp_state; attrib->sndmsg = sndmsg; attrib->encode = (optional ? MRP_ENCODE_OPTIONAL : MRP_ENCODE_YES); return 0; }