diff --git a/ZodiacFX/src/config/config_zodiac.h b/ZodiacFX/src/config/config_zodiac.h index 5c68505..52322cb 100644 --- a/ZodiacFX/src/config/config_zodiac.h +++ b/ZodiacFX/src/config/config_zodiac.h @@ -31,14 +31,14 @@ #define CONFIG_ZODIAC_H_ -#define VERSION "0.85" // Firmware version number +#define VERSION "0.86" // Firmware version number #define TOTAL_PORTS 4 // Total number of physical ports on the Zodiac FX #define MAX_OFP_VERSION 0x04 #define MAX_FLOWS_10 128 // Maximum number of flows for OpenFlow 1.0 -#define MAX_FLOWS_13 512 // Maximum number of flows for OpenFlow 1.3 +#define MAX_FLOWS_13 480 // Maximum number of flows for OpenFlow 1.3 #define MAX_VLANS 4 // Maximum number of VLANS, default is 1 per port (4) diff --git a/ZodiacFX/src/openflow/of_helper.c b/ZodiacFX/src/openflow/of_helper.c index 9976c6d..d3e71eb 100644 --- a/ZodiacFX/src/openflow/of_helper.c +++ b/ZodiacFX/src/openflow/of_helper.c @@ -336,6 +336,15 @@ void packet_fields_parser(uint8_t *pBuffer, struct packet_fields *fields) { fields->tp_dst = udphdr->dest; } } + + if(ntohs(fields->eth_prot) == 0x0806){ + memcpy(&fields->arp_op, fields->payload + 6, 2); + memcpy(&fields->arp_sha, fields->payload + 8, 6); + memcpy(&fields->arp_spa, fields->payload + 14, 4); + memcpy(&fields->arp_tha, fields->payload + 18, 6); + memcpy(&fields->arp_tpa, fields->payload + 24, 4); + } + fields->parsed = true; } @@ -578,7 +587,7 @@ int flowmatch13(uint8_t *pBuffer, int port, uint8_t table_id, struct packet_fiel break; case OXM_OF_MPLS_LABEL: - if (fields->isMPLSTag && fields->mpls_label != *(uint32_t*)oxm_value) + if (!(fields->isMPLSTag && ntohl(fields->mpls_label) == *(uint32_t*)oxm_value)) { priority_match = -1; } @@ -597,7 +606,129 @@ int flowmatch13(uint8_t *pBuffer, int port, uint8_t table_id, struct packet_fiel priority_match = -1; } break; + + case OXM_OF_ARP_OP: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + if (fields->arp_op != *(uint16_t*)oxm_value) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_SPA: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + if (memcmp(&fields->arp_spa, oxm_value, 4) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_SPA_W: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + memcpy(oxm_ipv4, &fields->arp_spa, 4); + for (int j=0; j<4; j++) + { + oxm_ipv4[j] &= oxm_value[4+j]; + } + if (memcmp(oxm_ipv4, oxm_value, 4) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_TPA: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + if (memcmp(&fields->arp_tpa, oxm_value, 4) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_TPA_W: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + memcpy(oxm_ipv4, &fields->arp_tpa, 4); + for (int j=0; j<4; j++) + { + oxm_ipv4[j] &= oxm_value[4+j]; + } + if (memcmp(oxm_ipv4, oxm_value, 4) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_SHA: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + if (memcmp(&fields->arp_sha, oxm_value, 6) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_SHA_W: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + for (int j=0; j<6; j++ ) + { + if ((oxm_value[j] & oxm_value[6+j]) != fields->arp_sha[j] & oxm_value[6+j]){ + priority_match = -1; + } + } + } + break; + case OXM_OF_ARP_THA: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + if (memcmp(&fields->arp_tha, oxm_value, 6) != 0) + { + priority_match = -1; + } + } + break; + + case OXM_OF_ARP_THA_W: + if (fields->eth_prot != htons(0x0806)) + { + priority_match = -1; + } else { + for (int j=0; j<6; j++ ) + { + if ((oxm_value[j] & oxm_value[6+j]) != fields->arp_tha[j] & oxm_value[6+j]){ + priority_match = -1; + } + } + } + break; + default: priority_match = -1; break; diff --git a/ZodiacFX/src/openflow/of_helper.h b/ZodiacFX/src/openflow/of_helper.h index 9dea30a..640a64b 100644 --- a/ZodiacFX/src/openflow/of_helper.h +++ b/ZodiacFX/src/openflow/of_helper.h @@ -44,6 +44,11 @@ struct packet_fields uint16_t vlanid; uint32_t ip_src; uint32_t ip_dst; + uint32_t arp_spa; + uint32_t arp_tpa; + uint32_t arp_op; + uint8_t arp_sha[6]; + uint8_t arp_tha[6]; uint32_t mpls_label; uint8_t mpls_tc; uint8_t mpls_bos; diff --git a/ZodiacFX/src/openflow/openflow.c b/ZodiacFX/src/openflow/openflow.c index 495c6d6..9867110 100644 --- a/ZodiacFX/src/openflow/openflow.c +++ b/ZodiacFX/src/openflow/openflow.c @@ -1,4 +1,6 @@ /** + * vi: ts=4:sw=4 + * * @file * openflow.c * @@ -73,15 +75,20 @@ int tcp_con_state = -1; int tcp_wait = 0; int totaltime = 0; int heartbeat = 0; -int multi_pos; uint32_t reply_more_xid = 0; bool reply_more_flag = false; bool rcv_freq; +// Buffer for multi-segment messages +#define PACKET_BUFFER_SIZE (2*TCP_MSS+64) // TODO: Ideally would be (2*1536) +static uint8_t packet_buffer[PACKET_BUFFER_SIZE]; +static unsigned int packet_buffer_off = 0; +static unsigned int packet_buffer_len = 0; + // Internal Functions void OF_hello(void); void echo_request(void); -void echo_reply(struct ofp_header *ofph, int size, int len); +void echo_reply(struct ofp_header *ofph, int len); err_t TCPready(void *arg, struct tcp_pcb *tpcb, err_t err); void tcp_error(void * arg, err_t err); static err_t of_receive(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err); @@ -133,43 +140,44 @@ void nnOF_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port) */ static err_t of_receive(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err) { - char *pc; - char packetbuffer[1536]; heartbeat = 0; // Reset heartbeat counter if (err == ERR_OK && p != NULL) { - tcp_recved(tpcb, p->tot_len); - pc=(char *)p->payload; //pointer to the payload - int len = p->tot_len; //size of the payload - for (int i=0; itot_len; //size of the payload + if (packet_buffer_len + plen > PACKET_BUFFER_SIZE) { + TRACE("openflow.c: packet buffer exceeded, aborting!!!"); + return ERR_ABRT; + } + memcpy(&packet_buffer[packet_buffer_len], p->payload, plen); // append to our own buffer + packet_buffer_len += plen; + TRACE("openflow.c: OpenFlow data received (%d bytes)", plen); + + // Accept the TCP data and release the packet + tcp_recved(tpcb, plen); + pbuf_free(p); + + while (packet_buffer_off < packet_buffer_len) { - ofph = &packetbuffer[size]; - if (size == 0) multi_pos = 0; + struct ofp_header *ofph = &packet_buffer[packet_buffer_off]; if (ofph->length == 0 || ofph->version == 0){ - return ERR_OK; //Not an OpenFlow packet + TRACE("openflow.c: Invalid OpenFlow packet, aborting!"); + return ERR_ABRT; } - plen = htons(ofph->length); - - if (ofph->version > 6 || ofph->type > 30) // Invalid OpenFlow message + if (ofph->version > 6 || ofph->type > 30) { - TRACE("openflow.c: Invalid OpenFlow command, ignoring!"); - return ERR_OK; + TRACE("openflow.c: Invalid OpenFlow packet values, aborting!"); + return ERR_ABRT; } - size = size + plen; - if (size > len) // corrupt OpenFlow command + + int ofp_len = htons(ofph->length); + if ((packet_buffer_off + ofp_len) > packet_buffer_len) { + // TRACE("openflow.c: Partial OpenFlow message - waiting for more data..."); break; - TRACE("openflow.c: Corrupt OpenFlow Message!!!"); } - TRACE("openflow.c: Processing %d byte OpenFlow message %u (%d)", plen, htonl(ofph->xid), size); + packet_buffer_off += ofp_len; + TRACE("openflow.c: Processing %d byte OpenFlow message %u", ofp_len, htonl(ofph->xid)); switch(ofph->type) { @@ -190,14 +198,24 @@ static err_t of_receive(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t e break; case OFPT10_ECHO_REQUEST: - echo_reply(ofph, size, len); + echo_reply(ofph, ofp_len); break; default: - if (OF_Version == 0x01) of10_message(ofph, size, len); - if (OF_Version == 0x04) of13_message(ofph, size, len); + if (OF_Version == 0x01) of10_message(ofph, ofp_len); + if (OF_Version == 0x04) of13_message(ofph, ofp_len); }; + } + if (packet_buffer_off == packet_buffer_len) { + packet_buffer_off = 0; + packet_buffer_len = 0; + } else { + unsigned int rem = packet_buffer_len - packet_buffer_off; + memcpy(packet_buffer, &packet_buffer[packet_buffer_off], rem); + packet_buffer_off = 0; + packet_buffer_len = rem; + TRACE("openflow.c: Partial OpenFlow message - keeping %d bytes", rem); } } else { pbuf_free(p); @@ -259,7 +277,7 @@ void OF_hello(void) * @param xid - transaction ID * */ -void echo_reply(struct ofp_header *ofph, int size, int len) +void echo_reply(struct ofp_header *ofph, int len) { // Change the message type to Echo Reply and return any data that was sent ofph->type = OFPT10_ECHO_REPLY; @@ -405,6 +423,8 @@ void task_openflow(void) */ err_t TCPready(void *arg, struct tcp_pcb *tpcb, err_t err) { + packet_buffer_off = 0; + packet_buffer_len = 0; tcp_con_state = true; tcp_recv(tpcb, of_receive); tcp_poll(tpcb, NULL, 4); diff --git a/ZodiacFX/src/openflow/openflow.h b/ZodiacFX/src/openflow/openflow.h index 014b125..6ddb02d 100644 --- a/ZodiacFX/src/openflow/openflow.h +++ b/ZodiacFX/src/openflow/openflow.h @@ -134,8 +134,8 @@ void task_openflow(void); void nnOF_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port); void nnOF10_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port); void nnOF13_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port); -void of10_message(struct ofp_header *ofph, int size, int len); -void of13_message(struct ofp_header *ofph, int size, int len); +void of10_message(struct ofp_header *ofph, int len); +void of13_message(struct ofp_header *ofph, int len); void multi_flow_more_reply13(void); void barrier10_reply(uint32_t xid); void barrier13_reply(uint32_t xid); diff --git a/ZodiacFX/src/openflow/openflow_10.c b/ZodiacFX/src/openflow/openflow_10.c index c5b4464..7a545e2 100644 --- a/ZodiacFX/src/openflow/openflow_10.c +++ b/ZodiacFX/src/openflow/openflow_10.c @@ -339,7 +339,7 @@ void nnOF10_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port) return; // Should only get to here if the action is unknown } -void of10_message(struct ofp_header *ofph, int size, int len) +void of10_message(struct ofp_header *ofph, int len) { struct ofp_stats_request *stats_req; switch(ofph->type) diff --git a/ZodiacFX/src/openflow/openflow_13.c b/ZodiacFX/src/openflow/openflow_13.c index a39e21b..236c16a 100644 --- a/ZodiacFX/src/openflow/openflow_13.c +++ b/ZodiacFX/src/openflow/openflow_13.c @@ -65,7 +65,6 @@ extern struct table_counter table_counters[MAX_TABLES]; extern uint8_t port_status[TOTAL_PORTS]; extern struct ofp_switch_config Switch_config; extern uint8_t shared_buffer[SHARED_BUFFER_LEN]; -extern int multi_pos; extern uint8_t NativePortMatrix; extern bool reply_more_flag; extern uint32_t reply_more_xid; @@ -356,14 +355,13 @@ void nnOF13_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port) mpls[2] &= 0xFE; // clear bottom stack bit } struct ofp13_action_push *push = (struct ofp13_action_push*)act_hdr; - memmove(fields.payload + 4, fields.payload-2, packet_size - 12); + memmove(fields.payload + 4, fields.payload, packet_size - 12); memcpy(fields.payload - 2, &push->ethertype, 2); memcpy(fields.payload, mpls, 4); - fields.payload += 6; - packet_size += 6; - *ul_size += 6; - fields.eth_prot = push->ethertype; - fields.isMPLSTag = true; + fields.payload += 4; + packet_size += 4; + *ul_size += 4; + packet_fields_parser(p_uc_data, &fields); } break; @@ -371,10 +369,11 @@ void nnOF13_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port) case OFPAT13_POP_MPLS: if(fields.isMPLSTag){ struct ofp13_action_pop_mpls *pop = (struct ofp13_action_pop_mpls*)act_hdr; - memmove(p_uc_data+12, p_uc_data+18, packet_size-18); - fields.payload -= 6; - packet_size -= 6; - *ul_size -= 6; + memmove(p_uc_data+14, p_uc_data+18, packet_size-16); + fields.payload -= 4; + memcpy(fields.payload - 2, &pop->ethertype, 2); + packet_size -= 4; + *ul_size -= 4; packet_fields_parser(p_uc_data, &fields); } break; @@ -663,9 +662,11 @@ void nnOF13_tablelookup(uint8_t *p_uc_data, uint32_t *ul_size, int port) return; } -void of13_message(struct ofp_header *ofph, int size, int len) +void of13_message(struct ofp_header *ofph, int len) { struct ofp13_multipart_request *multi_req; + int multi_len; + TRACE("openflow_13.c: %u: OpenFlow message received type = %d", htonl(ofph->xid), ofph->type); switch(ofph->type) { @@ -697,73 +698,84 @@ void of13_message(struct ofp_header *ofph, int size, int len) case OFPT13_MULTIPART_REQUEST: multi_req = (struct ofp13_multipart_request *) ofph; + if(multi_req->flags != 0) + { + TRACE("openflow_13.c: unsupported MULTIPART 'flags' request: %04x", multi_req->flags); + return; + } + if ( ntohs(multi_req->type) == OFPMP13_DESC ) { - multi_pos += multi_desc_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_desc_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_FLOW ) { - multi_pos += multi_flow_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_flow_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_AGGREGATE ) { - multi_pos += multi_aggregate_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_aggregate_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_PORT_STATS ) { - multi_pos += multi_portstats_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_portstats_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_PORT_DESC ) { - multi_pos += multi_portdesc_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_portdesc_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_METER ) { - multi_pos += multi_meter_stats_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_meter_stats_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_METER_CONFIG ) { - multi_pos += multi_meter_config_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_meter_config_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_METER_FEATURES ) { - multi_pos += multi_meter_features_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_meter_features_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_GROUP_FEATURES ) { - multi_pos += multi_group_features_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_group_features_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_GROUP_DESC ) { - multi_pos += multi_group_desc_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_group_desc_reply13(shared_buffer, multi_req); } if ( ntohs(multi_req->type) == OFPMP13_GROUP ) { - multi_pos += multi_group_stats_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_group_stats_reply13(shared_buffer, multi_req); } if ( htons(multi_req->type) == OFPMP13_TABLE_FEATURES ) { /**** Floodlight v1.2 crashes when it gets this reply, removed for the moment. *****/ - multi_pos += multi_tablefeat_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_tablefeat_reply13(shared_buffer, multi_req); //of_error13(ofph, OFPET13_BAD_REQUEST, OFPBRC13_BAD_TYPE); } if ( ntohs(multi_req->type) == OFPMP13_TABLE ) { - multi_pos += multi_table_reply13(&shared_buffer[multi_pos], multi_req); + multi_len = multi_table_reply13(shared_buffer, multi_req); } + + if (multi_len !=0) + { + sendtcp(shared_buffer, multi_len, 0); + } break; case OFPT10_PACKET_OUT: @@ -778,11 +790,6 @@ void of13_message(struct ofp_header *ofph, int size, int len) meter_mod13(ofph); break; }; - - if (size == len && multi_pos !=0) - { - sendtcp(&shared_buffer, multi_pos, 0); - } return; } @@ -1091,8 +1098,9 @@ int multi_portdesc_reply13(uint8_t *buffer, struct ofp13_multipart_request *msg) int multi_table_reply13(uint8_t *buffer, struct ofp13_multipart_request *msg) { int len = offsetof(struct ofp13_multipart_reply, body) + sizeof(struct ofp13_table_stats) * MAX_TABLES; - if (SHARED_BUFFER_LEN - multi_pos < len){ - return 0; // guard for buffer overrun + if (SHARED_BUFFER_LEN < len) { // guard for buffer overrun + TRACE("openflow_13.c: multi-table reply space exceeded, ignoring"); + return 0; } bzero(buffer, len); struct ofp13_multipart_reply *reply = buffer; diff --git a/ZodiacFX/src/openflow_spec/openflow_spec13.h b/ZodiacFX/src/openflow_spec/openflow_spec13.h index cb76e8b..d1db5f1 100644 --- a/ZodiacFX/src/openflow_spec/openflow_spec13.h +++ b/ZodiacFX/src/openflow_spec/openflow_spec13.h @@ -1498,7 +1498,9 @@ enum ofp_vlan_id { * * Masking: Not maskable. */ #define OXM_OF_ARP_SHA OXM_HEADER (0x8000, OFPXMT_OFB_ARP_SHA, 6) +#define OXM_OF_ARP_SHA_W OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_SHA, 6) #define OXM_OF_ARP_THA OXM_HEADER (0x8000, OFPXMT_OFB_ARP_THA, 6) +#define OXM_OF_ARP_THA_W OXM_HEADER_W(0x8000, OFPXMT_OFB_ARP_THA, 6) /* The source or destination address in the IPv6 header. * diff --git a/ZodiacFX/src/switch.c b/ZodiacFX/src/switch.c index 6454f41..e24c4cc 100644 --- a/ZodiacFX/src/switch.c +++ b/ZodiacFX/src/switch.c @@ -436,7 +436,7 @@ void switch_init(void) uint8_t vlanmaplow; vlanmaphigh = 16; // Set valid bit if (Zodiac_Config.vlan_list[x].uVlanType == 2) vlanmaphigh += 8; // Port 5 (CPU); - switch_write(80,2); // remove any VLAN tags going to the CPU + //switch_write(80,2); // remove any VLAN tags going to the CPU if (Zodiac_Config.vlan_list[x].portmap[3] == 1) // Port 4 { vlanmaphigh += 4; diff --git a/ZodiacFX_6_2.atsln b/ZodiacFX_6_2.atsln deleted file mode 100644 index 09d4d81..0000000 --- a/ZodiacFX_6_2.atsln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Atmel Studio Solution File, Format Version 11.00 -Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "ZodiacFX", "ZodiacFX\ZodiacFX_6_2.cproj", "{D48AA523-B6FA-4608-B329-EF580BA58EBA}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|ARM = Debug|ARM - Release|ARM = Release|ARM - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D48AA523-B6FA-4608-B329-EF580BA58EBA}.Debug|ARM.ActiveCfg = Debug|ARM - {D48AA523-B6FA-4608-B329-EF580BA58EBA}.Debug|ARM.Build.0 = Debug|ARM - {D48AA523-B6FA-4608-B329-EF580BA58EBA}.Release|ARM.ActiveCfg = Release|ARM - {D48AA523-B6FA-4608-B329-EF580BA58EBA}.Release|ARM.Build.0 = Release|ARM - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal