1 /****************************************************************************
2 Copyright (c) 2012, Intel Corporation
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
8 1. Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the Intel Corporation nor the names of its
16 contributors may be used to endorse or promote products derived from
17 this software without specific prior written permission.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 POSSIBILITY OF SUCH DAMAGE.
31 ******************************************************************************/
33 * MMRP protocol (part of 802.1Q-2011)
46 int mmrp_send_notifications(struct mmrp_attribute *attrib, int notify);
49 unsigned char MMRP_ADDR[] = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x20 };
51 extern unsigned char STATION_ADDR[];
55 struct mmrp_database *MMRP_db;
57 struct mmrp_attribute *mmrp_lookup(struct mmrp_attribute *rattrib)
59 struct mmrp_attribute *attrib;
62 attrib = MMRP_db->attrib_list;
63 while (NULL != attrib) {
64 if (rattrib->type == attrib->type) {
65 if (MMRP_SVCREQ_TYPE == attrib->type) {
66 /* this makes no sense to me ...
67 * its boolean .. but ..
69 if (attrib->attribute.svcreq ==
70 rattrib->attribute.svcreq)
73 mac_eq = memcmp(attrib->attribute.macaddr,
74 rattrib->attribute.macaddr, 6);
79 attrib = attrib->next;
84 int mmrp_add(struct mmrp_attribute *rattrib)
86 struct mmrp_attribute *attrib;
87 struct mmrp_attribute *attrib_tail;
90 /* XXX do a lookup first to guarantee uniqueness? */
92 attrib_tail = attrib = MMRP_db->attrib_list;
94 while (NULL != attrib) {
95 /* sort list into types, then sorted in order within types */
96 if (rattrib->type == attrib->type) {
97 if (MMRP_SVCREQ_TYPE == attrib->type) {
98 if (attrib->attribute.svcreq <
99 rattrib->attribute.svcreq) {
100 /* possible tail insertion ... */
102 if (NULL != attrib->next) {
103 if (MMRP_SVCREQ_TYPE ==
104 attrib->next->type) {
105 attrib = attrib->next;
110 rattrib->next = attrib->next;
111 rattrib->prev = attrib;
112 attrib->next = rattrib;
116 /* head insertion ... */
117 rattrib->next = attrib;
118 rattrib->prev = attrib->prev;
119 attrib->prev = rattrib;
120 if (NULL != rattrib->prev)
121 rattrib->prev->next = rattrib;
123 MMRP_db->attrib_list = rattrib;
128 mac_eq = memcmp(attrib->attribute.macaddr,
129 rattrib->attribute.macaddr, 6);
132 /* possible tail insertion ... */
134 if (NULL != attrib->next) {
135 if (MMRP_MACVEC_TYPE ==
136 attrib->next->type) {
137 attrib = attrib->next;
142 rattrib->next = attrib->next;
143 rattrib->prev = attrib;
144 attrib->next = rattrib;
148 /* head insertion ... */
149 rattrib->next = attrib;
150 rattrib->prev = attrib->prev;
151 attrib->prev = rattrib;
152 if (NULL != rattrib->prev)
153 rattrib->prev->next = rattrib;
155 MMRP_db->attrib_list = rattrib;
161 attrib_tail = attrib;
162 attrib = attrib->next;
165 /* if we are here we didn't need to stitch in a a sorted entry
166 * so append it onto the tail (if it exists)
169 if (NULL == attrib_tail) {
170 rattrib->next = NULL;
171 rattrib->prev = NULL;
172 MMRP_db->attrib_list = rattrib;
174 rattrib->next = NULL;
175 rattrib->prev = attrib_tail;
176 attrib_tail->next = rattrib;
182 int mmrp_merge(struct mmrp_attribute *rattrib)
184 struct mmrp_attribute *attrib;
186 attrib = mmrp_lookup(rattrib);
189 return -1; /* shouldn't happen */
191 /* primarily we update the last mac address state for diagnostics */
192 memcpy(attrib->registrar.macaddr, rattrib->registrar.macaddr, 6);
196 int mmrp_event(int event, struct mmrp_attribute *rattrib)
198 struct mmrp_attribute *attrib;
201 case MRP_EVENT_LVATIMER:
202 mrp_jointimer_stop(&(MMRP_db->mrp_db));
204 attrib = MMRP_db->attrib_list;
206 while (NULL != attrib) {
207 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TXLA);
208 mrp_registrar_fsm(&(attrib->registrar),
209 &(MMRP_db->mrp_db), MRP_EVENT_TXLA);
210 attrib = attrib->next;
213 mrp_lvatimer_fsm(&(MMRP_db->mrp_db), MRP_EVENT_LVATIMER);
218 mrp_jointimer_stop(&(MMRP_db->mrp_db));
220 attrib = MMRP_db->attrib_list;
222 while (NULL != attrib) {
223 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_RLA);
224 mrp_registrar_fsm(&(attrib->registrar),
225 &(MMRP_db->mrp_db), MRP_EVENT_RLA);
226 attrib = attrib->next;
229 mrp_lvatimer_fsm(&(MMRP_db->mrp_db), MRP_EVENT_RLA);
233 mrp_jointimer_stop(&(MMRP_db->mrp_db));
234 attrib = MMRP_db->attrib_list;
236 while (NULL != attrib) {
237 mrp_applicant_fsm(&(attrib->applicant), MRP_EVENT_TX);
238 attrib = attrib->next;
241 mrp_lvatimer_fsm(&(MMRP_db->mrp_db), MRP_EVENT_TX);
245 case MRP_EVENT_LVTIMER:
246 mrp_lvtimer_stop(&(MMRP_db->mrp_db));
247 attrib = MMRP_db->attrib_list;
249 while (NULL != attrib) {
250 mrp_registrar_fsm(&(attrib->registrar),
254 attrib = attrib->next;
257 case MRP_EVENT_PERIODIC:
258 attrib = MMRP_db->attrib_list;
260 while (NULL != attrib) {
261 mrp_applicant_fsm(&(attrib->applicant),
263 attrib = attrib->next;
269 case MRP_EVENT_RJOININ:
270 case MRP_EVENT_RJOINMT:
275 mrp_jointimer_start(&(MMRP_db->mrp_db));
277 return -1; /* XXX internal fault */
280 attrib = mmrp_lookup(rattrib);
282 if (NULL == attrib) {
290 mrp_applicant_fsm(&(attrib->applicant), event);
291 /* remap local requests into registrar events */
294 mrp_registrar_fsm(&(attrib->registrar),
295 &(MMRP_db->mrp_db), MRP_EVENT_RNEW);
298 if (MRP_IN_STATE == attrib->registrar.mrp_state)
299 mrp_registrar_fsm(&(attrib->registrar),
303 mrp_registrar_fsm(&(attrib->registrar),
308 mrp_registrar_fsm(&(attrib->registrar),
309 &(MMRP_db->mrp_db), MRP_EVENT_RLV);
312 mrp_registrar_fsm(&(attrib->registrar),
313 &(MMRP_db->mrp_db), event);
322 * XXX should honor the MMRP_db->mrp_db.registration and
323 * MMRP_db->mrp_db.participant controls
326 /* generate local notifications */
327 attrib = MMRP_db->attrib_list;
329 while (NULL != attrib) {
330 if (MRP_NOTIFY_NONE != attrib->registrar.notify) {
331 mmrp_send_notifications(attrib,
332 attrib->registrar.notify);
333 attrib->registrar.notify = MRP_NOTIFY_NONE;
335 attrib = attrib->next;
341 struct mmrp_attribute *mmrp_alloc()
343 struct mmrp_attribute *attrib;
345 attrib = malloc(sizeof(struct mmrp_attribute));
349 memset(attrib, 0, sizeof(struct mmrp_attribute));
351 attrib->applicant.mrp_state = MRP_VO_STATE;
352 attrib->applicant.tx = 0;
353 attrib->applicant.sndmsg = MRP_SND_NULL;
354 attrib->applicant.encode = MRP_ENCODE_OPTIONAL;
356 attrib->registrar.mrp_state = MRP_MT_STATE;
357 attrib->registrar.notify = MRP_NOTIFY_NONE;
362 void mmrp_increment_macaddr(uint8_t * macaddr)
369 if (255 != macaddr[i]) {
385 mrpdu_message_t *mrpdu_msg;
386 unsigned char *mrpdu_msg_ptr;
387 unsigned char *mrpdu_msg_eof;
388 mrpdu_vectorattrib_t *mrpdu_vectorptr;
390 uint16_t numvalues_processed;
396 uint8_t svcreq_firstval;
397 uint8_t macvec_firstval[6];
398 struct mmrp_attribute *attrib;
401 bytes = mrpd_recvmsgbuf(mmrp_socket, &msgbuf);
405 if ((unsigned int)bytes < (sizeof(eth_hdr_t) + sizeof(mrpdu_t) +
406 sizeof(mrpdu_message_t)))
409 eth = (eth_hdr_t *) msgbuf;
411 /* note that MMRP frames should always arrive untagged (no vlan) */
412 if (MMRP_ETYPE != ntohs(eth->typelen))
415 /* XXX check dest mac address too? */
417 mrpdu = (mrpdu_t *) (msgbuf + sizeof(struct eth_hdr));
419 if (MMRP_PROT_VER != mrpdu->ProtocolVersion) /* should accept */
422 mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
424 mrpdu_msg_eof = (unsigned char *)mrpdu_msg_ptr;
425 mrpdu_msg_eof += bytes;
426 mrpdu_msg_eof -= sizeof(eth_hdr_t);
427 mrpdu_msg_eof -= MRPD_OFFSETOF_MRPD_GET_MRPDU_MESSAGE_LIST;
431 while (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
432 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
433 if ((mrpdu_msg->AttributeType == 0) &&
434 (mrpdu_msg->AttributeLength == 0)) {
438 continue; /* end-mark */
440 break; /* two endmarks - end of messages */
443 endmarks = 0; /* reset the endmark counter */
445 switch (mrpdu_msg->AttributeType) {
446 case MMRP_SVCREQ_TYPE:
447 if (mrpdu_msg->AttributeLength != 1) {
448 /* we could seek for an endmark to recover
452 /* AttributeListLength not used for MMRP, hence
453 * Data points to the beginning of the VectorAttributes
456 (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
457 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
459 while (!((mrpdu_msg_ptr[0] == 0)
460 && (mrpdu_msg_ptr[1] == 0))) {
462 MRPDU_VECT_NUMVALUES(ntohs
467 /* Malformed - cant tell how long the trailing vectors are */
470 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
471 numvalues / 3) >= mrpdu_msg_eof)
472 /* Malformed - runs off the end of the pdu */
476 mrpdu_vectorptr->FirstValue_VectorEvents[0];
478 /* if not an even multiple ... */
479 if (numvalues != ((numvalues / 3) * 3))
480 numvectorbytes = (numvalues / 3) + 1;
482 numvectorbytes = (numvalues / 3);
485 vectidx <= (numvectorbytes + 1);
489 FirstValue_VectorEvents[vectidx];
490 vectevt[0] = vect_3pack / 36;
492 (vect_3pack - vectevt[0] * 36) / 6;
494 vect_3pack - (36 * vectevt[0]) -
497 numvalues_processed =
498 (numvalues > 3 ? 3 : numvalues);
500 for (vectevt_idx = 0;
501 vectevt_idx < numvalues_processed;
504 if (1 < svcreq_firstval) /*discard junk */
507 attrib = mmrp_alloc();
509 goto out; /* oops - internal error */
511 attrib->type = MMRP_SVCREQ_TYPE;
512 attrib->attribute.svcreq =
515 memcpy(attrib->registrar.
516 macaddr, eth->srcaddr,
519 switch (vectevt[vectevt_idx]) {
555 numvalues -= numvalues_processed;
558 /* as either firstval is either 0 or 1 ... the common
559 * case will be nulls for evt_2 and evt_3 ...
562 (ntohs(mrpdu_vectorptr->VectorHeader)))
563 mmrp_event(MRP_EVENT_RLA, NULL);
565 /* 2 byte numvalues + 34 byte FirstValue + (n) vector bytes */
566 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
567 mrpdu_msg_ptr += 3 + numvectorbytes;
569 (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
573 case MMRP_MACVEC_TYPE:
574 if (mrpdu_msg->AttributeLength != 6) {
575 /* we can seek for an endmark to recover .. but this version
576 * dumps the entire packet as malformed
580 /* AttributeListLength not used for MMRP, hence
581 * Data points to the beginning of the VectorAttributes
584 (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
585 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
587 while (!((mrpdu_msg_ptr[0] == 0)
588 && (mrpdu_msg_ptr[1] == 0))) {
590 MRPDU_VECT_NUMVALUES(ntohs
595 /* Malformed - cant tell how long the trailing vectors are */
598 if ((mrpdu_vectorptr->FirstValue_VectorEvents +
599 numvalues / 3) >= mrpdu_msg_eof)
600 /* Malformed - runs off the end of the pdu */
603 memcpy(macvec_firstval,
604 mrpdu_vectorptr->FirstValue_VectorEvents,
607 /* if not an even multiple ... */
608 if (numvalues != ((numvalues / 3) * 3))
609 numvectorbytes = (numvalues / 3) + 1;
611 numvectorbytes = (numvalues / 3);
614 vectidx <= (numvectorbytes + 6);
618 FirstValue_VectorEvents[vectidx];
619 vectevt[0] = vect_3pack / 36;
621 (vect_3pack - vectevt[0] * 36) / 6;
623 vect_3pack - (36 * vectevt[0]) -
626 numvalues_processed =
627 (numvalues > 3 ? 3 : numvalues);
629 for (vectevt_idx = 0;
630 vectevt_idx < numvalues_processed;
633 attrib = mmrp_alloc();
635 goto out; /* oops - internal error */
637 attrib->type = MMRP_MACVEC_TYPE;
638 memcpy(attrib->attribute.
639 macaddr, macvec_firstval,
641 mmrp_increment_macaddr
644 memcpy(attrib->registrar.
645 macaddr, eth->srcaddr,
648 switch (vectevt[vectevt_idx]) {
684 numvalues -= numvalues_processed;
688 (ntohs(mrpdu_vectorptr->VectorHeader)))
689 mmrp_event(MRP_EVENT_RLA, NULL);
691 /* 1 byte Type, 1 byte Len, 6 byte FirstValue, and (n) vector bytes */
692 mrpdu_msg_ptr = (uint8_t *) mrpdu_vectorptr;
693 mrpdu_msg_ptr += 8 + numvectorbytes;
696 (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
700 /* unrecognized attribute type
701 * we can seek for an endmark to recover .. but this version
702 * dumps the entire packet as malformed
717 mmrp_emit_svcvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
718 int *bytes_used, int lva)
720 mrpdu_vectorattrib_t *mrpdu_vectorptr;
726 uint8_t svcreq_firstval;
727 struct mmrp_attribute *attrib, *vattrib;
728 mrpdu_message_t *mrpdu_msg;
729 unsigned char *mrpdu_msg_ptr = msgbuf;
730 unsigned char *mrpdu_msg_eof = msgbuf_eof;
732 /* need at least 6 bytes for a single vector */
733 if (mrpdu_msg_ptr > (mrpdu_msg_eof - 6))
736 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
737 mrpdu_msg->AttributeType = MMRP_SVCREQ_TYPE;
738 mrpdu_msg->AttributeLength = 1;
740 attrib = MMRP_db->attrib_list;
742 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
744 while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
746 if (MMRP_SVCREQ_TYPE != attrib->type) {
747 attrib = attrib->next;
751 if (0 == attrib->applicant.tx) {
752 attrib = attrib->next;
755 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
756 attrib->applicant.tx = 0;
757 attrib = attrib->next;
761 /* pointing to at least one attribute which needs to be transmitted */
762 svcreq_firstval = attrib->attribute.svcreq;
763 mrpdu_vectorptr->FirstValue_VectorEvents[0] =
764 attrib->attribute.svcreq;
766 switch (attrib->applicant.sndmsg) {
769 * If 'In' in indicated by the applicant attribute, the
770 * look at the registrar state to determine whether to
771 * send an In (if registrar is also In) or an Mt if the
772 * registrar is either Mt or Lv.
774 if (MRP_IN_STATE == attrib->registrar.mrp_state)
775 vectevt[0] = MRPDU_IN;
777 vectevt[0] = MRPDU_MT;
780 vectevt[0] = MRPDU_NEW;
783 vectevt[0] = MRPDU_LV;
786 /* IF 'Join' in indicated by the applicant, look at
787 * the corresponding registrar state to determine whether
788 * to send a JoinIn (if the registar state is 'In') or
789 * a JoinMt if the registrar state is MT or LV.
791 if (MRP_IN_STATE == attrib->registrar.mrp_state)
792 vectevt[0] = MRPDU_JOININ;
794 vectevt[0] = MRPDU_JOINMT;
805 /* now attempt to vectorize contiguous other attributes
806 * which also need to be transmitted
810 vattrib = attrib->next;
812 while (NULL != vattrib) {
813 if (MMRP_SVCREQ_TYPE != vattrib->type)
816 if (0 == vattrib->applicant.tx)
821 if (vattrib->attribute.svcreq != svcreq_firstval)
824 vattrib->applicant.tx = 0;
826 switch (vattrib->applicant.sndmsg) {
829 * If 'In' in indicated by the applicant attribute, the
830 * look at the registrar state to determine whether to
831 * send an In (if registrar is also In) or an Mt if the
832 * registrar is either Mt or Lv.
835 vattrib->registrar.mrp_state)
836 vectevt[vectevt_idx] = MRPDU_IN;
838 vectevt[vectevt_idx] = MRPDU_MT;
841 vectevt[vectevt_idx] = MRPDU_NEW;
844 vectevt[vectevt_idx] = MRPDU_LV;
847 /* IF 'Join' in indicated by the applicant, look at
848 * the corresponding registrar state to determine whether
849 * to send a JoinIn (if the registar state is 'In') or
850 * a JoinMt if the registrar state is MT or LV.
852 if (MRP_IN_STATE == attrib->registrar.mrp_state)
853 vectevt[vectevt_idx] = MRPDU_JOININ;
855 vectevt[vectevt_idx] = MRPDU_JOINMT;
866 if (vectevt_idx > 2) {
867 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
871 mrpdu_vectorptr->FirstValue_VectorEvents
872 [vectidx] = vect_3pack;
880 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
881 > (mrpdu_msg_eof - 2))
884 vattrib = vattrib->next;
887 /* handle any trailers */
888 if (vectevt_idx > 0) {
889 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
890 vectevt[1], vectevt[2]);
892 mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
897 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
901 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
904 mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
906 mrpdu_vectorptr->VectorHeader =
907 htons(mrpdu_vectorptr->VectorHeader);
909 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
911 &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
913 attrib = attrib->next;
915 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
919 if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *) mrpdu_msg->Data) {
930 *bytes_used = (mrpdu_msg_ptr - msgbuf);
933 /* an internal error - caller should assume TXLAF */
939 mmrp_emit_macvectors(unsigned char *msgbuf, unsigned char *msgbuf_eof,
940 int *bytes_used, int lva)
942 mrpdu_vectorattrib_t *mrpdu_vectorptr;
943 mrpdu_message_t *mrpdu_msg;
944 unsigned char *mrpdu_msg_ptr = msgbuf;
945 unsigned char *mrpdu_msg_eof = msgbuf_eof;
951 uint8_t macvec_firstval[6];
952 struct mmrp_attribute *attrib, *vattrib;
955 /* need at least 11 bytes for a single vector */
956 if (mrpdu_msg_ptr > (mrpdu_msg_eof - 11))
959 mrpdu_msg = (mrpdu_message_t *) mrpdu_msg_ptr;
960 mrpdu_msg->AttributeType = MMRP_MACVEC_TYPE;
961 mrpdu_msg->AttributeLength = 6;
963 attrib = MMRP_db->attrib_list;
965 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg->Data;
967 while ((mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) && (NULL != attrib)) {
969 if (MMRP_MACVEC_TYPE != attrib->type) {
970 attrib = attrib->next;
974 if (0 == attrib->applicant.tx) {
975 attrib = attrib->next;
978 if (MRP_ENCODE_OPTIONAL == attrib->applicant.encode) {
979 attrib->applicant.tx = 0;
980 attrib = attrib->next;
984 /* pointing to at least one attribute which needs to be transmitted */
985 memcpy(macvec_firstval, attrib->attribute.macaddr, 6);
986 memcpy(mrpdu_vectorptr->FirstValue_VectorEvents,
987 attrib->attribute.macaddr, 6);
989 switch (attrib->applicant.sndmsg) {
992 * If 'In' in indicated by the applicant attribute, the
993 * look at the registrar state to determine whether to
994 * send an In (if registrar is also In) or an Mt if the
995 * registrar is either Mt or Lv.
997 if (MRP_IN_STATE == attrib->registrar.mrp_state)
998 vectevt[0] = MRPDU_IN;
1000 vectevt[0] = MRPDU_MT;
1003 vectevt[0] = MRPDU_NEW;
1006 vectevt[0] = MRPDU_LV;
1009 /* IF 'Join' in indicated by the applicant, look at
1010 * the corresponding registrar state to determine whether
1011 * to send a JoinIn (if the registar state is 'In') or
1012 * a JoinMt if the registrar state is MT or LV.
1014 if (MRP_IN_STATE == attrib->registrar.mrp_state)
1015 vectevt[0] = MRPDU_JOININ;
1017 vectevt[0] = MRPDU_JOINMT;
1031 /* now attempt to vectorize contiguous other attributes
1032 * which also need to be transmitted
1036 vattrib = attrib->next;
1038 while (NULL != vattrib) {
1039 if (MMRP_MACVEC_TYPE != vattrib->type)
1042 if (0 == vattrib->applicant.tx)
1045 mmrp_increment_macaddr(macvec_firstval);
1048 memcmp(vattrib->attribute.macaddr, macvec_firstval,
1054 vattrib->applicant.tx = 0;
1056 switch (vattrib->applicant.sndmsg) {
1059 * If 'In' in indicated by the applicant attribute, the
1060 * look at the registrar state to determine whether to
1061 * send an In (if registrar is also In) or an Mt if the
1062 * registrar is either Mt or Lv.
1065 vattrib->registrar.mrp_state)
1066 vectevt[vectevt_idx] = MRPDU_IN;
1068 vectevt[vectevt_idx] = MRPDU_MT;
1071 vectevt[vectevt_idx] = MRPDU_NEW;
1074 vectevt[vectevt_idx] = MRPDU_LV;
1077 /* IF 'Join' in indicated by the applicant, look at
1078 * the corresponding registrar state to determine whether
1079 * to send a JoinIn (if the registar state is 'In') or
1080 * a JoinMt if the registrar state is MT or LV.
1082 if (MRP_IN_STATE == attrib->registrar.mrp_state)
1083 vectevt[vectevt_idx] = MRPDU_JOININ;
1085 vectevt[vectevt_idx] = MRPDU_JOINMT;
1096 if (vectevt_idx > 2) {
1097 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1101 mrpdu_vectorptr->FirstValue_VectorEvents
1102 [vectidx] = vect_3pack;
1110 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx])
1111 > (mrpdu_msg_eof - 11))
1114 vattrib = vattrib->next;
1117 /* handle any trailers */
1118 if (vectevt_idx > 0) {
1119 vect_3pack = MRPDU_3PACK_ENCODE(vectevt[0],
1120 vectevt[1], vectevt[2]);
1122 mrpdu_vectorptr->FirstValue_VectorEvents[vectidx] =
1127 if (&(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]) >
1128 (mrpdu_msg_eof - 2))
1131 mrpdu_vectorptr->VectorHeader = MRPDU_VECT_NUMVALUES(numvalues);
1134 mrpdu_vectorptr->VectorHeader |= MRPDU_VECT_LVA(0xFFFF);
1136 mrpdu_vectorptr->VectorHeader =
1137 htons(mrpdu_vectorptr->VectorHeader);
1139 /* 2 byte header, followed by FirstValues/Vectors - remember vectidx starts at 0 */
1141 &(mrpdu_vectorptr->FirstValue_VectorEvents[vectidx]);
1143 attrib = attrib->next;
1145 mrpdu_vectorptr = (mrpdu_vectorattrib_t *) mrpdu_msg_ptr;
1148 if (mrpdu_vectorptr == (mrpdu_vectorattrib_t *) mrpdu_msg->Data) {
1159 *bytes_used = (mrpdu_msg_ptr - msgbuf);
1162 /* an internal error - caller should assume TXLAF */
1167 int mmrp_txpdu(void)
1169 unsigned char *msgbuf, *msgbuf_wrptr;
1174 unsigned char *mrpdu_msg_ptr;
1175 unsigned char *mrpdu_msg_eof;
1179 msgbuf = (unsigned char *)malloc(MAX_FRAME_SIZE);
1184 msgbuf_wrptr = msgbuf;
1186 eth = (eth_hdr_t *) msgbuf_wrptr;
1188 /* note that MMRP frames should always be untagged (no vlan) */
1189 eth->typelen = htons(MMRP_ETYPE);
1190 memcpy(eth->destaddr, MMRP_ADDR, sizeof(eth->destaddr));
1191 memcpy(eth->srcaddr, STATION_ADDR, sizeof(eth->srcaddr));
1193 msgbuf_wrptr += sizeof(eth_hdr_t);
1195 mrpdu = (mrpdu_t *) msgbuf_wrptr;
1198 * ProtocolVersion handling - a receiver must process received frames with a lesser
1199 * protcol version consistent with the older protocol processing requirements (e.g. a V2
1200 * agent receives a V1 message, the V1 message shoudl be parsed with V1 rules).
1202 * However - if an agent receives a NEWER protocol, the agent shoudl still attempt
1203 * to parse the frame. If the agent finds an AttributeType not recognized
1204 * the agent discards the current message including any associated trailing vectors
1205 * up to the end-mark, and resumes with the next message or until the end of the PDU
1208 * If a VectorAttribute is found with an unknown Event for the Type, the specific
1209 * VectorAttrute is discarded and processing continues with the next VectorAttribute.
1212 mrpdu->ProtocolVersion = MMRP_PROT_VER;
1213 mrpdu_msg_ptr = MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu);
1214 mrpdu_msg_eof = (unsigned char *)msgbuf + MAX_FRAME_SIZE;
1217 * Iterate over all attributes, transmitting those marked
1218 * with 'tx', attempting to coalesce multiple contiguous tx attributes
1219 * with appropriate vector encodings.
1221 * MMRP_MACVEC_TYPE FirstValue is the 6-byte MAC address, with
1222 * corresponding attrib_length=6
1224 * MMRP_SVCREQ_TYPE FirstValue is a single byte - values follow,
1227 * MMRP uses ThreePackedEvents for all vector encodings
1229 * the expanded version of the MRPDU looks like
1233 * <Variable number of>
1234 * LeaveAllEvent | NumberOfValues
1235 * <Variable FirstValue>
1236 * <VectorEventBytes>
1239 * in effect, each AttributeType present gets its own 'message' with
1240 * variable number of vectors. So with MMRP, you will have at most
1241 * two messages (SVCREQ or MACVEC)
1244 if (MMRP_db->mrp_db.lva.tx) {
1246 MMRP_db->mrp_db.lva.tx = 0;
1249 rc = mmrp_emit_macvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
1253 mrpdu_msg_ptr += bytes;
1255 if (mrpdu_msg_ptr >= (mrpdu_msg_eof - 2))
1258 rc = mmrp_emit_svcvectors(mrpdu_msg_ptr, mrpdu_msg_eof, &bytes, lva);
1262 mrpdu_msg_ptr += bytes;
1266 if (mrpdu_msg_ptr == MRPD_GET_MRPDU_MESSAGE_LIST(mrpdu)) {
1271 if (mrpdu_msg_ptr < (mrpdu_msg_eof - 2)) {
1279 msgbuf_len = mrpdu_msg_ptr - msgbuf;
1281 bytes = mrpd_send(mmrp_socket, msgbuf, msgbuf_len, 0);
1289 /* caller should assume TXLAF */
1293 int mmrp_send_notifications(struct mmrp_attribute *attrib, int notify)
1304 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
1308 stage = variant = regsrc = NULL;
1310 stage = (char *)malloc(128);
1311 variant = (char *)malloc(128);
1312 regsrc = (char *)malloc(128);
1314 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
1317 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
1319 if (MMRP_SVCREQ_TYPE == attrib->type) {
1320 sprintf(variant, "S=%d", attrib->attribute.svcreq);
1322 sprintf(variant, "M=%02x%02x%02x%02x%02x%02x",
1323 attrib->attribute.macaddr[0],
1324 attrib->attribute.macaddr[1],
1325 attrib->attribute.macaddr[2],
1326 attrib->attribute.macaddr[3],
1327 attrib->attribute.macaddr[4],
1328 attrib->attribute.macaddr[5]);
1331 sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x",
1332 attrib->registrar.macaddr[0],
1333 attrib->registrar.macaddr[1],
1334 attrib->registrar.macaddr[2],
1335 attrib->registrar.macaddr[3],
1336 attrib->registrar.macaddr[4], attrib->registrar.macaddr[5]);
1337 switch (attrib->registrar.mrp_state) {
1339 sprintf(stage, "MIN %s %s\n", variant, regsrc);
1342 sprintf(stage, "MLV %s %s\n", variant, regsrc);
1345 sprintf(stage, "MMT %s %s\n", variant, regsrc);
1352 case MRP_NOTIFY_NEW:
1353 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "MNE %s", stage);
1355 case MRP_NOTIFY_JOIN:
1356 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "MJO %s", stage);
1359 snprintf(msgbuf, MAX_MRPD_CMDSZ - 1, "MLE %s", stage);
1366 client = MMRP_db->mrp_db.clients;
1367 while (NULL != client) {
1368 mrpd_send_ctl_msg(&(client->client), msgbuf, MAX_MRPD_CMDSZ);
1369 client = client->next;
1383 int mmrp_dumptable(struct sockaddr_in *client)
1390 struct mmrp_attribute *attrib;
1392 msgbuf = (char *)malloc(MAX_MRPD_CMDSZ);
1396 stage = variant = regsrc = NULL;
1398 stage = (char *)malloc(128);
1399 variant = (char *)malloc(128);
1400 regsrc = (char *)malloc(128);
1402 if ((NULL == stage) || (NULL == variant) || (NULL == regsrc))
1405 memset(msgbuf, 0, MAX_MRPD_CMDSZ);
1407 msgbuf_wrptr = msgbuf;
1409 attrib = MMRP_db->attrib_list;
1411 if (attrib == NULL) {
1412 sprintf(msgbuf, "Empty");
1415 while (NULL != attrib) {
1416 if (MMRP_SVCREQ_TYPE == attrib->type) {
1417 sprintf(variant, "S=%d", attrib->attribute.svcreq);
1419 sprintf(variant, "M=%02x%02x%02x%02x%02x%02x",
1420 attrib->attribute.macaddr[0],
1421 attrib->attribute.macaddr[1],
1422 attrib->attribute.macaddr[2],
1423 attrib->attribute.macaddr[3],
1424 attrib->attribute.macaddr[4],
1425 attrib->attribute.macaddr[5]);
1427 sprintf(regsrc, "R=%02x%02x%02x%02x%02x%02x",
1428 attrib->registrar.macaddr[0],
1429 attrib->registrar.macaddr[1],
1430 attrib->registrar.macaddr[2],
1431 attrib->registrar.macaddr[3],
1432 attrib->registrar.macaddr[4],
1433 attrib->registrar.macaddr[5]);
1434 switch (attrib->registrar.mrp_state) {
1436 sprintf(stage, "MIN %s %s\n", variant, regsrc);
1439 sprintf(stage, "MLV %s %s\n", variant, regsrc);
1442 sprintf(stage, "MMT %s %s\n", variant, regsrc);
1447 sprintf(msgbuf_wrptr, "%s", stage);
1448 msgbuf_wrptr += strnlen(stage, 128);
1449 attrib = attrib->next;
1452 mrpd_send_ctl_msg(client, msgbuf, MAX_MRPD_CMDSZ);
1466 int mmrp_cmd_parse_mac(
1467 char *buf, int buflen,
1472 struct parse_param specs[] = {
1473 {"M" PARSE_ASSIGN, parse_mac, mac},
1479 return parse(buf + 4, buflen - 4, specs, err_index);
1485 struct mmrp_attribute *attrib;
1486 attrib = mmrp_alloc();
1489 attrib->type = MMRP_MACVEC_TYPE;
1490 memcpy(attrib->attribute.macaddr, mac, 6);
1491 mmrp_event(mrp_event, attrib);
1494 int mmrp_cmd_parse_service(
1495 char *buf, int buflen,
1500 struct parse_param specs[] = {
1501 {"S" PARSE_ASSIGN, parse_u8, service},
1507 return parse(buf + 4, buflen - 4, specs, err_index);
1510 int mmrp_cmd_service(
1514 struct mmrp_attribute *attrib;
1515 attrib = mmrp_alloc();
1518 attrib->type = MMRP_SVCREQ_TYPE;
1519 attrib->attribute.svcreq = service;
1520 mmrp_event(mrp_event, attrib);
1524 int mmrp_recv_cmd(char *buf, int buflen, struct sockaddr_in *client)
1529 uint8_t svcreq_param;
1530 uint8_t macvec_param[6];
1532 if (NULL == MMRP_db) {
1533 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1534 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1538 rc = mrp_client_add(&(MMRP_db->mrp_db.clients), client);
1547 * M?? - query MMRP Registrar MAC Address database
1548 * M+? - JOIN a MAC address or service declaration
1549 * M++ NEW a MAC Address (XXX: MMRP doesn't use 'New' though?)
1550 * M-- - LV a MAC address or service declaration
1552 if (strncmp(buf, "M??", 3) == 0) {
1553 mmrp_dumptable(client);
1554 } else if (strncmp(buf, "M--:S", 5) == 0) {
1555 rc = mmrp_cmd_parse_service(buf, buflen, &svcreq_param,
1559 rc = mmrp_cmd_service(svcreq_param, MRP_EVENT_LV);
1562 } else if ( strncmp(buf, "M--:M", 5) == 0) {
1564 * XXX note could also register VID with mac address if we ever wanted to
1565 * support more than one Spanning Tree context
1568 /* buf[] should look similar to 'M--:M=010203040506' */
1569 rc = mmrp_cmd_parse_mac(buf, buflen, macvec_param,
1573 rc = mmrp_cmd_mac(macvec_param, MRP_EVENT_LV);
1576 } else if ((strncmp(buf, "M++:S", 5) == 0) || (strncmp(buf, "M+?S", 4) == 0)){
1577 /* buf[] should look similar to 'M+?:S=1' or 'M++:S=1'
1579 rc = mmrp_cmd_parse_service(buf, buflen, &svcreq_param,
1583 rc = mmrp_cmd_service(svcreq_param, MRP_EVENT_JOIN);
1586 } else if ( strncmp(buf, "M++:M", 5) == 0) {
1587 /* buf[] should look similar to 'M+?:M=010203040506' */
1588 rc = mmrp_cmd_parse_mac(buf, buflen, macvec_param,
1592 rc = mmrp_cmd_mac(macvec_param, MRP_EVENT_JOIN);
1596 snprintf(respbuf, sizeof(respbuf) - 1, "ERC %s", buf);
1597 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1604 snprintf(respbuf, sizeof(respbuf) - 1, "ERI %s", buf);
1605 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1609 snprintf(respbuf, sizeof(respbuf) - 1, "ERP %s", buf);
1610 mrpd_send_ctl_msg(client, respbuf, sizeof(respbuf));
1617 int mmrp_init(int mmrp_enable)
1621 /* XXX doesn't handle re-start */
1623 mmrp_socket = INVALID_SOCKET;
1626 if (0 == mmrp_enable) {
1630 rc = mrpd_init_protocol_socket(MMRP_ETYPE, &mmrp_socket, MMRP_ADDR);
1634 MMRP_db = malloc(sizeof(struct mmrp_database));
1636 if (NULL == MMRP_db)
1639 memset(MMRP_db, 0, sizeof(struct mmrp_database));
1641 /* if registration is FIXED or FORBIDDEN
1642 * updates from MRP are discarded, and
1643 * only IN and JOININ messages are sent
1645 MMRP_db->mrp_db.registration = MRP_REGISTRAR_CTL_NORMAL; /* default */
1647 /* if participant role is 'SILENT' (or non-participant)
1648 * applicant doesn't send any messages -
1650 * Note - theoretically configured per-attribute
1652 MMRP_db->mrp_db.participant = MRP_APPLICANT_CTL_NORMAL; /* default */
1654 rc = mrpd_init_timers(&(MMRP_db->mrp_db));
1659 mrp_lvatimer_fsm(&(MMRP_db->mrp_db), MRP_EVENT_BEGIN);
1663 /* free MMRP_db and related structures */
1667 mrpd_close_socket(mmrp_socket);
1668 mmrp_socket = INVALID_SOCKET;
1675 int mmrp_reclaim(void)
1677 struct mmrp_attribute *mattrib, *free_mattrib;
1679 if (NULL == MMRP_db)
1682 mattrib = MMRP_db->attrib_list;
1683 while (NULL != mattrib) {
1684 if ((mattrib->registrar.mrp_state == MRP_MT_STATE) &&
1685 ((mattrib->applicant.mrp_state == MRP_VO_STATE) ||
1686 (mattrib->applicant.mrp_state == MRP_AO_STATE) ||
1687 (mattrib->applicant.mrp_state == MRP_QO_STATE))) {
1688 if (NULL != mattrib->prev)
1689 mattrib->prev->next = mattrib->next;
1691 MMRP_db->attrib_list = mattrib->next;
1692 if (NULL != mattrib->next)
1693 mattrib->next->prev = mattrib->prev;
1694 free_mattrib = mattrib;
1695 mattrib = mattrib->next;
1696 mmrp_send_notifications(free_mattrib, MRP_NOTIFY_LV);
1699 mattrib = mattrib->next;
1704 void mmrp_bye(struct sockaddr_in *client)
1706 if (NULL != MMRP_db)
1707 mrp_client_delete(&(MMRP_db->mrp_db.clients), client);