1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | /* * openflow协议处理入口函数 为了节省篇幅删除一些case语句。 */ static enum ofperr handle_openflow__(struct ofconn *ofconn, const struct ofpbuf *msg) OVS_EXCLUDED(ofproto_mutex) { const struct ofp_header *oh = msg->data; /* 从ofpbuf获取数据 */ enum ofptype type; enum ofperr error; /* openflow协议头解码 这个函数是我们介绍重点 */ error = ofptype_decode(&type, oh); if (error) { return error; } if (oh->version >= OFP13_VERSION && ofpmsg_is_stat_request(oh) && ofpmp_more(oh)) { /* We have no buffer implementation for multipart requests. * Report overflow for requests which consists of multiple * messages. */ return OFPERR_OFPBRC_MULTIPART_BUFFER_OVERFLOW; } /* * 根据不同type进行不同处理消息 */ switch (type) { /* OpenFlow requests. */ case OFPTYPE_ECHO_REQUEST: return handle_echo_request(ofconn, oh); case OFPTYPE_PACKET_OUT: /* packet out消息 */ return handle_packet_out(ofconn, oh); case OFPTYPE_PORT_MOD: return handle_port_mod(ofconn, oh); case OFPTYPE_FLOW_MOD: return handle_flow_mod(ofconn, oh); ... case OFPTYPE_BARRIER_REQUEST: /* barrier消息 没有做什么啊!! */ return handle_barrier_request(ofconn, oh); case OFPTYPE_ROLE_REQUEST: return handle_role_request(ofconn, oh); case OFPTYPE_TABLE_STATS_REQUEST: return handle_table_stats_request(ofconn, oh); case OFPTYPE_TABLE_FEATURES_STATS_REQUEST: return handle_table_features_request(ofconn, oh); .... case OFPTYPE_HELLO: case OFPTYPE_ERROR: case OFPTYPE_FEATURES_REPLY: case OFPTYPE_GET_CONFIG_REPLY: case OFPTYPE_PACKET_IN: /* PACKET_IN消息 */ ... case OFPTYPE_METER_FEATURES_STATS_REPLY: case OFPTYPE_TABLE_FEATURES_STATS_REPLY: case OFPTYPE_ROLE_STATUS: default: if (ofpmsg_is_stat_request(oh)) { return OFPERR_OFPBRC_BAD_STAT; } else { return OFPERR_OFPBRC_BAD_TYPE; } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | /* * 解析openflow头部,如果存在子类型则会进一步解析,针对报文图2就会进一步解码。 * 参数1:出参 */ static enum ofperr ofphdrs_decode(struct ofphdrs *hdrs, const struct ofp_header *oh, size_t length) { memset(hdrs, 0, sizeof *hdrs); if (length < sizeof *oh) { return OFPERR_OFPBRC_BAD_LEN; } /* 获取基本消息版本号和类型,如果当前消息存在子类型就会进入if-else分支进一步解析子类型,反之直接退出。*/ hdrs->version = oh->version; hdrs->type = oh->type; /* 如果存在子类型就会进入if-else分支进一步解析,针对上面两种报文,图1不会进入任何一个分支,而图2则会进入else分支。为了节省篇幅,我们只针对常见消息进行解析—openflow1.3消息。 */ if (hdrs->type == OFPT_VENDOR) {//获取设备厂商信息 ... } else if (hdrs->version == OFP10_VERSION && (hdrs->type == OFPT10_STATS_REQUEST || hdrs->type == OFPT10_STATS_REPLY)) {//openflow1.0的消息,我们不关系 ... } else if (hdrs->version != OFP10_VERSION && (hdrs->type == OFPT11_STATS_REQUEST || hdrs->type == OFPT11_STATS_REPLY)) {/* 通过报文和代码中枚举类型可知,图2中报文会进入此分支。 */ const struct ofp11_stats_msg *osm; /* Get statistic type (OFPST_*). */ if (length < sizeof *osm) { return OFPERR_OFPBRC_BAD_LEN; } osm = (const struct ofp11_stats_msg *) oh; hdrs->stat = ntohs(osm->type);/* 将子类型赋值到出参的stat中 */ if (hdrs->stat == OFPST_VENDOR) {/* 这个分支也是获取厂商信息 对于上面消息而言不会进入,我们这里忽略掉。 */ } } return 0; } 这个函数我们就分析完了,我们来看一下这个函数:ofpraw_from_ofphdrs。 /* * 通过上面函数得到hdrs(参数2)传入到这个函数中,以便获取raw。 */ static enum ofperr ofpraw_from_ofphdrs(enum ofpraw *raw, const struct ofphdrs *hdrs) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); struct raw_instance *raw_hdrs; uint32_t hash; ofpmsgs_init; hash = ofphdrs_hash(hdrs);/* 对参数2进行hash运算,然后在hash-map中查找 */ HMAP_FOR_EACH_WITH_HASH (raw_hdrs, hmap_node, hash, &raw_instance_map) { if (ofphdrs_equal(hdrs, &raw_hdrs->hdrs)) { *raw = raw_hdrs->raw;/* 返回找到raw类型 */ return 0; } } /* 如果没有找则记录日志并且返回错误 */ if (!VLOG_DROP_WARN(&rl)) { struct ds s; ds_init(&s); ds_put_format(&s, "version %"PRIu8", type %"PRIu8, hdrs->version, hdrs->type); if (ofphdrs_is_stat(hdrs)) { ds_put_format(&s, ", stat %"PRIu16, hdrs->stat); } if (hdrs->vendor) { ds_put_format(&s, ", vendor 0x%"PRIx32", subtype %"PRIu32, hdrs->vendor, hdrs->subtype); } VLOG_WARN("unknown OpenFlow message (%s)", ds_cstr(&s)); ds_destroy(&s); } return (hdrs->vendor ? OFPERR_OFPBRC_BAD_SUBTYPE : ofphdrs_is_stat(hdrs) ? OFPERR_OFPBRC_BAD_STAT : OFPERR_OFPBRC_BAD_TYPE); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /* Information about a particular &#39;enum ofpraw&#39;. */ struct raw_info { /* All possible instantiations of this OFPRAW_* into OpenFlow headers. */ struct raw_instance *instances; /* 这个是一个数组,其数组大小是min_version - max_version + 1. */ uint8_t min_version; /* 当前实例支持的最小版本号 最小是1*/ uint8_t max_version; /* 当前实例支持的最大版本号 最大是255*/ unsigned int min_body; /* 消息体最小大小 */ unsigned int extra_multiple;/* 这个字段不是很明白是什么意思 */ enum ofptype type;/* openflow消息类型,例如OFPTYPE_HELLO,OFPTYPE_PACKET_IN等 */ const char *name;/* 字符描述 */ }; /* A mapping from OpenFlow headers to OFPRAW_*. */ struct raw_instance { struct hmap_node hmap_node; /* In &#39;raw_instance_map&#39;. Hash节点*/ struct ofphdrs hdrs; /* Key. Hash-key*/ enum ofpraw raw; /* Value. */ unsigned int hdrs_len; /* ofphdrs_len(hdrs). */ }; 我们来分析两个两个消息,一个是hello消息,一个是flow_mod消息。 static struct raw_info raw_infos = { { ofpraw_ofpt_hello_instances, /* 实例定义 */ 1, 255,/* 最小版本号1说明hello消息是从openflow1.0开始, 最大版本号是255说明,这个hello消息在各个版本中都支持。*/ #line 109 "./lib/ofp-msgs.h" 0,/* 最小消息体长度是0,表明没有消息体 */ #line 109 "./lib/ofp-msgs.h" sizeof(uint8_t), #line 1620 "lib/ofp-msgs.inc" OFPTYPE_HELLO,/* openflow消息类型,消息类型是hello消息 */ "OFPT_HELLO", /* 字符描述 */ }, ... { ofpraw_ofpt10_flow_mod_instances,/* openflow1.0中flow_mod */ 1, 1, /* 最小和最大版本号都是1,表明这个flow_mod消息支持1.0 */ #line 175 "./lib/ofp-msgs.h" sizeof(struct ofp10_flow_mod), #line 175 "./lib/ofp-msgs.h" sizeof(uint8_t[8]), #line 1884 "lib/ofp-msgs.inc" OFPTYPE_FLOW_MOD, "OFPT_FLOW_MOD", }, { ofpraw_ofpt11_flow_mod_instances, /* openflow1.1协议中flow_mod */ 2, 6, /* 最小版本号是2,最大版本号是6,表明这个flow_mod支持openflow1.1到openflow1.5。 */ #line 177 "./lib/ofp-msgs.h" sizeof(struct ofp11_flow_mod),/* 标准openflow中flow_mod结构大小 */ #line 177 "./lib/ofp-msgs.h" sizeof(struct ofp11_instruction), /*扩展结构,即instruction结构*/ #line 1895 "lib/ofp-msgs.inc" OFPTYPE_FLOW_MOD, "OFPT_FLOW_MOD", }, } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | enum ofperr ofpraw_pull(enum ofpraw *rawp, struct ofpbuf *msg) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); const struct raw_instance *instance; const struct raw_info *info; struct ofphdrs hdrs; unsigned int min_len; unsigned int len; enum ofperr error; enum ofpraw raw; /* Set default outputs. */ msg->header = msg->data; msg->msg = msg->header; *rawp = 0; len = msg->size; error = ofphdrs_decode(&hdrs, msg->data, len);/* 解析openflow头部消息 保存在hdrs中 */ if (error) { return error; } error = ofpraw_from_ofphdrs(&raw, &hdrs); /* 根据hdrs,从hmap中获取raw */ if (error) { return error; } /* 获取实例对象 */ info = raw_info_get(raw); instance = raw_instance_get(info, hdrs.version); /* 根据实例对象配置,进行数据分割。 */ msg->header = ofpbuf_pull(msg, instance->hdrs_len); msg->msg = msg->data; min_len = instance->hdrs_len + info->min_body; switch (info->extra_multiple) { case 0: if (len != min_len) { VLOG_WARN_RL(&rl, "received %s with incorrect length %u (expected " "length %u)", info->name, len, min_len); return OFPERR_OFPBRC_BAD_LEN; } break; case 1: if (len < min_len) { VLOG_WARN_RL(&rl, "received %s with incorrect length %u (expected " "length at least %u bytes)", info->name, len, min_len); return OFPERR_OFPBRC_BAD_LEN; } break; default: if (len < min_len || (len - min_len) % info->extra_multiple) { VLOG_WARN_RL(&rl, "received %s with incorrect length %u (must be " "exactly %u bytes or longer by an integer multiple " "of %u bytes)", info->name, len, min_len, info->extra_multiple); return OFPERR_OFPBRC_BAD_LEN; } break; } *rawp = raw; /* 返回从实例中获取raw类型。 */ return 0; } |
欢迎光临 51学通信论坛2017新版 (http://bbs.51xuetongxin.com/) | Powered by Discuz! X3 |