Skip to content
Eder Leão Fernandes edited this page Sep 13, 2018 · 1 revision

Support for rewriting packet fields exists since the first OpenFlow version. However, it was limited to a small set of fields. In OpenFlow 1.3, with the OXM introduction, a flow mod message can carry a set field action with any of the OXMs defined by the specification. It is up for the switch designers to decide which fields are allowed for overwrite.

Implementation of set field is slightly intricate, as the consistence is achieved through the match fields. For instance, a flow with a set field action to rewrite the IP source address needs to present in the match fields the same ethertype - 0x800 in hexadecimal - of the IP protocol. The way the pack and unpack of match fields and actions is performed by different functions needs to be checked in the Datapath. When handling a new flow mod message, the Flow Table calls the function dp_actions_check_set_field_req. This function uses an Oflib function to check if the prerequisites are ok and validates the action.

Another frequent task caused by rewriting fields is protocol CheckSum recalculation. Fields like the IP source and destination, in the case of change, require recalculation of IP and TCP CheckSum values. Fortunately these protocols' CheckSum calculation is very simple. This is not the case for the SCTP protocol. SCTP CheckSum is calculated using a Cyclic Redundancy Check (CRC). In order to recalculate the SCTP CheckSum value we used a Python program named pycrc. The program takes as input the CRC polynomial and generates all the functions necessary for the calculations.

The code below shows the code to rewrite the SCTP destination port. In the packet field rewriting we attribute a pointer to the protocol struct representation and to the packet position obtained by the Packet Parser. Doing so, we can easily change the current value of the action value.

case OXM_OF_SCTP_DST:{
                crc_t crc;
                struct sctp_header *sctp = pkt->handle_std->proto->sctp;                
                size_t len = ((uint8_t*) ofpbuf_tail(pkt->handle_std->pkt->buffer)) - (uint8_t *) sctp;
                uint16_t v = htons(*(uint16_t*) act->field->value);
                sctp->sctp_csum = 0;
                memcpy(&sctp->sctp_dst, &v, OXM_LENGTH(act->field->header));
                crc = crc_init();
                crc = crc_update(crc, (unsigned char*)sctp, len);                            
                crc = crc_finalize(crc);
                sctp->sctp_csum = crc;
                break;        
            }