Finite State Machine represented by static Arrays

Source: Internet
Author: User
Some time ago, I made a stateless TCP conntrack and found that one of the static arrays represents a good TCP state machine. I hope this idea can be used in practical work. Let's just say, this is the state machine array:
static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {    {/* ORIGINAL *//*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2    *//*syn*/       { sSS, sSS, sIG, sIG, sIG, sIG, sIG, sSS, sSS, sS2 },/*...};

The following is the state machine conversion formula:
New_state = tcp_conntracks [dir] [Index] [old_state];
In the above formula, DIR is ip_ct_dir_reply or ip_ct_dir_original, and index is actually an event. At first glance, we can see that this is more than a while loop state machine, because the state machine is completely digitalized, instead of using the code logic such as if State-if event or switch-case. When this array is filled, the if State-if event and other judgments are completed. The array is filled and used directly.
In fact, in the Linux kernel, such an implementation is not only conntrack, ipvs is also a good example, net/Netfilter/ipvs/ip_vs_proto_tcp.c:

static struct tcp_states_t tcp_states [] = {/*    INPUT *//*        sNO, sES, sSS, sSR, sFW, sTW, sCL, sCW, sLA, sLI, sSA    *//*syn*/ {{sSR, sES, sES, sSR, sSR, sSR, sSR, sSR, sSR, sSR, sSR }},/*fin*/ {{sCL, sCW, sSS, sTW, sTW, sTW, sCL, sCW, sLA, sLI, sTW }},/*ack*/ {{sCL, sES, sSS, sES, sFW, sTW, sCL, sCW, sCL, sLI, sES }},/*rst*/ {{sCL, sCL, sCL, sSR, sCL, sCL, sCL, sCL, sLA, sLI, sSR }},...};

It can be seen that it is extremely similar to ip_conntrack! This array contains a large amount of information, and almost uses index subscript and array dimension to store data. This forms a multi-dimensional storage structure. Once the information of the two dimensions is no longer orthogonal, the array element itself has a state, and this is the key to implementing the state machine.

Here is an example of a general state machine.

We need to use this state machine to construct an array, fill each element, and write the static array. in the H file, if the computer has its own intelligence, the filling work can be completed at runtime. However, the computer has no intelligence, so it can only be written by programmers. If the code needs to be filled during running, the code that fills the Code itself returns to the while loop processing state machine.
The filling process is simple. The formula is as follows:
Statemachine [event] [oldsate] = newstate;
To this end, we first define a set of data to digitize the state and event:

/* State definition */Enum state {state0 = 0, statea = 1, Stateb = 2, STATEC = 3,};/* event definition */Enum event {einit = 0, evt0a = 1, evta0 = 2, evtac = 3, evtc0 = 4, evtcb = 5, evtbc = 6 ,};

We define a two-dimensional array. The first dimension represents the event, and the second-dimensional value represents the second-dimensional Index of the next state, which is actually the following formula.
Newstate = statemachine [event] [oldstate];
According to the filling rules above, we finally get the following array:

StateMachine[][]={/*Einit*/       {State0,}/*Evt0A*/    {StateA,},/*EvtA0*/    {stub,State0,},/*EvtAC*/    {stub,StateC,},/*EvtC0*/    {stub,stub,stub,State0,},/*EvtCB*/    {stub,stub,StateB,},/*EvtBC*/    {stub,stub,StateC,},}

Stub indicates that there is no status.

After reading this example, let's look back at the example of ip_conntrack and ipvs's TCP state machine array, which is clearer. The only difference is that, ip_conntrack uses a new dimension to represent the data direction, while ipvs uses a base + offset method to locate the index of the event dimension array. Finally, we made the above process into a figure:

Summary:

We know that any program can be represented as a state machine, which is also the essence of the program. It is essentially the form below:
If (match0 ){
Do_something0;
} Elif (mattings ){
Do_something1;
} Elif (match2 ){
Do_something2;
}
Any logic that can be expressed in this way can be expressed in a multi-dimensional array. Common filtering mechanisms, such as BPF, are essentially overlay judgments:
If (match0 & match1 & match2 & Match 3 &&...){
Return true;
} Else {
Return false;
}
Using each match as a dimension of the array, You can construct an array, the final judgment on whether to match is converted into whether the element of the target position indicated by the index of each dimension of the array calculated based on many matches is null (or stub in the preceding simple example ). But it's slow! The above idea has a premise that the person or program that fills the array must know the result in advance. For the existing finite state machine, this is certainly true, however, for the above multi-match element matching, the filling person does not know the result before getting the input (a bit nonsense, if he knows the result, what should he do with the Judgment program !!), Therefore, the input must also be included in the array. Therefore, the input must be limited. After all, the array must be finite.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.