Openvswitch原理与代码分析(4): 修改Openvswitch代码添加自定义action

xiaoxiao2021-02-28  106

有时候我们需要自定义一些自己的action,根据包头里面的信息,做一些自己的操作。

 

例如添加一个action名为handle_example

 

第一、修改ofp-actions.c文件

 

首先在ofp-actions.c里面添加Openflow各个版本的这个action

staticconststruct ofpact_map * get_ofpact_map(enum ofp_version version) {     /* OpenFlow 1.0 actions. */     staticconststruct ofpact_map of10[] = {         { OFPACT_OUTPUT, 0 },         { OFPACT_SET_VLAN_VID, 1 },         { OFPACT_SET_VLAN_PCP, 2 },         { OFPACT_STRIP_VLAN, 3 },         { OFPACT_SET_ETH_SRC, 4 },         { OFPACT_SET_ETH_DST, 5 },         { OFPACT_SET_IPV4_SRC, 6 },         { OFPACT_SET_IPV4_DST, 7 },         { OFPACT_SET_IP_DSCP, 8 },         { OFPACT_SET_L4_SRC_PORT, 9 },         { OFPACT_SET_L4_DST_PORT, 10 },         { OFPACT_ENQUEUE, 11 },         { OFPACT_HANDLE_EXAMPLE, 28 },         { 0, -1 },     };       /* OpenFlow 1.1 actions. */     staticconststruct ofpact_map of11[] = {         { OFPACT_OUTPUT, 0 },         { OFPACT_SET_VLAN_VID, 1 },         { OFPACT_SET_VLAN_PCP, 2 },         { OFPACT_SET_ETH_SRC, 3 },         { OFPACT_SET_ETH_DST, 4 },         { OFPACT_SET_IPV4_SRC, 5 },         { OFPACT_SET_IPV4_DST, 6 },         { OFPACT_SET_IP_DSCP, 7 },         { OFPACT_SET_IP_ECN, 8 },         { OFPACT_SET_L4_SRC_PORT, 9 },         { OFPACT_SET_L4_DST_PORT, 10 },         /* OFPAT_COPY_TTL_OUT (11) not supported. */         /* OFPAT_COPY_TTL_IN (12) not supported. */         { OFPACT_SET_MPLS_LABEL, 13 },         { OFPACT_SET_MPLS_TC, 14 },         { OFPACT_SET_MPLS_TTL, 15 },         { OFPACT_DEC_MPLS_TTL, 16 },         { OFPACT_PUSH_VLAN, 17 },         { OFPACT_STRIP_VLAN, 18 },         { OFPACT_PUSH_MPLS, 19 },         { OFPACT_POP_MPLS, 20 },         { OFPACT_SET_QUEUE, 21 },         { OFPACT_GROUP, 22 },         { OFPACT_SET_IP_TTL, 23 },         { OFPACT_DEC_TTL, 24 },         { OFPACT_HANDLE_EXAMPLE, 28 },         { 0, -1 },     };       /* OpenFlow 1.2, 1.3, and 1.4 actions. */     staticconststruct ofpact_map of12[] = {         { OFPACT_OUTPUT, 0 },         /* OFPAT_COPY_TTL_OUT (11) not supported. */         /* OFPAT_COPY_TTL_IN (12) not supported. */         { OFPACT_SET_MPLS_TTL, 15 },         { OFPACT_DEC_MPLS_TTL, 16 },         { OFPACT_PUSH_VLAN, 17 },         { OFPACT_STRIP_VLAN, 18 },         { OFPACT_PUSH_MPLS, 19 },         { OFPACT_POP_MPLS, 20 },         { OFPACT_SET_QUEUE, 21 },         { OFPACT_GROUP, 22 },         { OFPACT_SET_IP_TTL, 23 },         { OFPACT_DEC_TTL, 24 },         { OFPACT_SET_FIELD, 25 },         /* OF1.3+ OFPAT_PUSH_PBB (26) not supported. */         /* OF1.3+ OFPAT_POP_PBB (27) not supported. */         { OFPACT_HANDLE_EXAMPLE, 28 },         { 0, -1 },     };       switch (version) {     case OFP10_VERSION:         return of10;       case OFP11_VERSION:         return of11;       case OFP12_VERSION:     case OFP13_VERSION:     case OFP14_VERSION:     case OFP15_VERSION:     default:         return of12;     } }

 

其次添加raw action type

enum ofp_raw_action_type { /* ## ----------------- ## */ /* ## Standard actions. ## */ /* ## ----------------- ## */       /* OF1.0(0): struct ofp10_action_output. */     OFPAT_RAW10_OUTPUT,     /* OF1.1+(0): struct ofp11_action_output. */     OFPAT_RAW11_OUTPUT,       /* OF1.0(1): uint16_t. */     OFPAT_RAW10_SET_VLAN_VID,     /* OF1.0(2): uint8_t. */     OFPAT_RAW10_SET_VLAN_PCP,       /* OF1.1(1), OF1.2+(1) is deprecated (use Set-Field): uint16_t.      *      * [Semantics differ slightly between the 1.0 and 1.1 versions of the VLAN      * modification actions: the 1.0 versions push a VLAN header if none is      * present, but the 1.1 versions do not. That is the only reason that we      * distinguish their raw action types.] */     OFPAT_RAW11_SET_VLAN_VID,     /* OF1.1(2), OF1.2+(2) is deprecated (use Set-Field): uint8_t. */     OFPAT_RAW11_SET_VLAN_PCP,       /* OF1.1+(17): ovs_be16.      *      * [The argument is the Ethertype, e.g. ETH_TYPE_VLAN_8021Q, not the VID or      * TCI.] */     OFPAT_RAW11_PUSH_VLAN,       /* OF1.0(3): void. */     OFPAT_RAW10_STRIP_VLAN,     /* OF1.1+(18): void. */     OFPAT_RAW11_POP_VLAN,       /* OF1.0(4), OF1.1(3), OF1.2+(3) is deprecated (use Set-Field): struct      * ofp_action_dl_addr. */     OFPAT_RAW_SET_DL_SRC,       /* OF1.0(5), OF1.1(4), OF1.2+(4) is deprecated (use Set-Field): struct      * ofp_action_dl_addr. */     OFPAT_RAW_SET_DL_DST,       /* OF1.0(6), OF1.1(5), OF1.2+(5) is deprecated (use Set-Field):      * ovs_be32. */     OFPAT_RAW_SET_NW_SRC,       /* OF1.0(7), OF1.1(6), OF1.2+(6) is deprecated (use Set-Field):      * ovs_be32. */     OFPAT_RAW_SET_NW_DST,       /* OF1.0(8), OF1.1(7), OF1.2+(7) is deprecated (use Set-Field): uint8_t. */     OFPAT_RAW_SET_NW_TOS,       /* OF1.1(8), OF1.2+(8) is deprecated (use Set-Field): uint8_t. */     OFPAT_RAW11_SET_NW_ECN,       /* OF1.0(9), OF1.1(9), OF1.2+(9) is deprecated (use Set-Field):      * ovs_be16. */     OFPAT_RAW_SET_TP_SRC,       /* OF1.0(10), OF1.1(10), OF1.2+(10) is deprecated (use Set-Field):      * ovs_be16. */     OFPAT_RAW_SET_TP_DST,       /* OF1.0(11): struct ofp10_action_enqueue. */     OFPAT_RAW10_ENQUEUE,       /* NX1.0(30), OF1.1(13), OF1.2+(13) is deprecated (use Set-Field):      * ovs_be32. */     OFPAT_RAW_SET_MPLS_LABEL,       /* NX1.0(31), OF1.1(14), OF1.2+(14) is deprecated (use Set-Field):      * uint8_t. */     OFPAT_RAW_SET_MPLS_TC,       /* NX1.0(25), OF1.1(15), OF1.2+(15) is deprecated (use Set-Field):      * uint8_t. */     OFPAT_RAW_SET_MPLS_TTL,       /* NX1.0(26), OF1.1+(16): void. */     OFPAT_RAW_DEC_MPLS_TTL,       /* NX1.0(23), OF1.1+(19): ovs_be16.      *      * [The argument is the Ethertype, e.g. ETH_TYPE_MPLS, not the label.] */     OFPAT_RAW_PUSH_MPLS,       /* NX1.0(24), OF1.1+(20): ovs_be16.      *      * [The argument is the Ethertype, e.g. ETH_TYPE_IPV4 if at BoS or      * ETH_TYPE_MPLS otherwise, not the label.] */     OFPAT_RAW_POP_MPLS,       /* NX1.0(4), OF1.1+(21): uint32_t. */     OFPAT_RAW_SET_QUEUE,       /* OF1.1+(22): uint32_t. */     OFPAT_RAW11_GROUP,       /* OF1.1+(23): uint8_t. */     OFPAT_RAW11_SET_NW_TTL,       /* NX1.0(18), OF1.1+(24): void. */     OFPAT_RAW_DEC_NW_TTL,     /* NX1.0+(21): struct nx_action_cnt_ids, ... */     NXAST_RAW_DEC_TTL_CNT_IDS,       /* OF1.2-1.4(25): struct ofp12_action_set_field, ... */     OFPAT_RAW12_SET_FIELD,     /* OF1.5+(25): struct ofp12_action_set_field, ... */     OFPAT_RAW15_SET_FIELD,       /* OF1.0(28): void. */     OFPAT_RAW10_HANDLE_EXAMPLE,       /* OF1.1(28): void. */     OFPAT_RAW11_HANDLE_EXAMPLE,       /* OF1.2-1.4(28): void. */     OFPAT_RAW12_HANDLE_EXAMPLE,       /* NX1.0-1.4(7): struct nx_action_reg_load.      *      * [In OpenFlow 1.5, set_field is a superset of reg_load functionality, so      * we drop reg_load.] */     NXAST_RAW_REG_LOAD,     /* NX1.0-1.4(33): struct nx_action_reg_load2, ...      *      * [In OpenFlow 1.5, set_field is a superset of reg_load2 functionality, so      * we drop reg_load2.] */     NXAST_RAW_REG_LOAD2,       /* OF1.5+(28): struct ofp15_action_copy_field, ... */     OFPAT_RAW15_COPY_FIELD,     /* ONF1.3-1.4(3200): struct onf_action_copy_field, ... */     ONFACT_RAW13_COPY_FIELD,     /* NX1.0-1.4(6): struct nx_action_reg_move, ... */     NXAST_RAW_REG_MOVE,   /* ## ------------------------- ## */ /* ## Nicira extension actions. ## */ /* ## ------------------------- ## */   /* Actions similar to standard actions are listed with the standard actions. */       /* NX1.0+(1): uint16_t. */     NXAST_RAW_RESUBMIT,     /* NX1.0+(14): struct nx_action_resubmit. */     NXAST_RAW_RESUBMIT_TABLE,       /* NX1.0+(2): uint32_t. */     NXAST_RAW_SET_TUNNEL,     /* NX1.0+(9): uint64_t. */     NXAST_RAW_SET_TUNNEL64,       /* NX1.0+(5): void. */     NXAST_RAW_POP_QUEUE,       /* NX1.0+(8): struct nx_action_note, ... */     NXAST_RAW_NOTE,       /* NX1.0+(10): struct nx_action_multipath. */     NXAST_RAW_MULTIPATH,       /* NX1.0+(12): struct nx_action_bundle, ... */     NXAST_RAW_BUNDLE,     /* NX1.0+(13): struct nx_action_bundle, ... */     NXAST_RAW_BUNDLE_LOAD,       /* NX1.0+(15): struct nx_action_output_reg. */     NXAST_RAW_OUTPUT_REG,     /* NX1.0+(32): struct nx_action_output_reg2. */     NXAST_RAW_OUTPUT_REG2,       /* NX1.0+(16): struct nx_action_learn, ... */     NXAST_RAW_LEARN,       /* NX1.0+(17): void. */     NXAST_RAW_EXIT,       /* NX1.0+(19): struct nx_action_fin_timeout. */     NXAST_RAW_FIN_TIMEOUT,       /* NX1.0+(20): struct nx_action_controller. */     NXAST_RAW_CONTROLLER,       /* NX1.0+(22): struct nx_action_write_metadata. */     NXAST_RAW_WRITE_METADATA,       /* NX1.0+(27): struct nx_action_stack. */     NXAST_RAW_STACK_PUSH,       /* NX1.0+(28): struct nx_action_stack. */     NXAST_RAW_STACK_POP,       /* NX1.0+(29): struct nx_action_sample. */     NXAST_RAW_SAMPLE,       /* NX1.0+(34): struct nx_action_conjunction. */     NXAST_RAW_CONJUNCTION,       /* NX1.0+(35): struct nx_action_conntrack, ... */     NXAST_RAW_CT,   /* ## ------------------ ## */ /* ## Debugging actions. ## */ /* ## ------------------ ## */   /* These are intentionally undocumented, subject to change, and ovs-vswitchd */ /* accepts them only if started with --enable-dummy. */       /* NX1.0+(255): void. */     NXAST_RAW_DEBUG_RECIRC, };

 

第三,添加handle example的action的处理函数

/* handle gtp actions. */ staticenum ofperr decode_OFPAT_RAW10_HANDLE_EXAMPLE(struct ofpbuf *out) {     ofpact_put_HANDLE_EXAMPLE(out)->ofpact.raw = OFPAT_RAW10_HANDLE_EXAMPLE;     return 0; }   staticenum ofperr decode_OFPAT_RAW11_HANDLE_EXAMPLE(struct ofpbuf *out) {     ofpact_put_HANDLE_EXAMPLE(out)->ofpact.raw = OFPAT_RAW11_HANDLE_EXAMPLE;     return 0; }   staticenum ofperr decode_OFPAT_RAW12_HANDLE_EXAMPLE(struct ofpbuf *out) {     ofpact_put_HANDLE_EXAMPLE(out)->ofpact.raw = OFPAT_RAW12_HANDLE_EXAMPLE;     return 0; }   staticvoid encode_HANDLE_EXAMPLE(conststruct ofpact_null *null OVS_UNUSED,                   enum ofp_version ofp_version, struct ofpbuf *out) {     if (ofp_version == OFP10_VERSION) {         put_OFPAT10_HANDLE_EXAMPLE(out);     } elseif (ofp_version == OFP11_VERSION) {         put_OFPAT11_HANDLE_EXAMPLE(out);     } else {         put_OFPAT12_HANDLE_EXAMPLE(out);     } }   staticchar * OVS_WARN_UNUSED_RESULT parse_HANDLE_EXAMPLE(char *arg OVS_UNUSED, struct ofpbuf *ofpacts,                  enum ofputil_protocol *usable_protocols OVS_UNUSED) {     ofpact_put_HANDLE_EXAMPLE(ofpacts)->ofpact.raw = OFPAT_RAW10_HANDLE_EXAMPLE;     return NULL; }   staticvoid format_HANDLE_EXAMPLE(conststruct ofpact_null *a OVS_UNUSED, struct ds *s) {     ds_put_cstr(s, "handle_example"); }

 

struct ofpact * ofpact_next_flattened(conststruct ofpact *ofpact) { switch (ofpact->type) { case OFPACT_HANDLE_EXAMPLE:

 

staticbool ofpact_is_set_or_move_action(conststruct ofpact *a) {     switch (a->type) {     case OFPACT_HANDLE_EXAMPLE: return true;

 

staticbool ofpact_is_allowed_in_actions_set(conststruct ofpact *a) {     switch (a->type) {     case OFPACT_HANDLE_EXAMPLE: return true;

 

enum ovs_instruction_type ovs_instruction_type_from_ofpact_type(enum ofpact_type type) {     switch (type) {     case OFPACT_HANDLE_EXAMPLE:

 

staticenum ofperr ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a,                struct flow *flow, ofp_port_t max_ports,                uint8_t table_id, uint8_t n_tables) {     conststruct ofpact_enqueue *enqueue;     conststruct mf_field *mf;       switch (a->type) {     case OFPACT_HANDLE_EXAMPLE:         return 0;

 

staticbool ofpact_outputs_to_port(conststruct ofpact *ofpact, ofp_port_t port) {     switch (ofpact->type) {     case OFPACT_HANDLE_EXAMPLE:     default:         returnfalse;

 

第二,修改文件ofp-actions.h

 

#define OFPACTS \     /* Output. */ \     OFPACT(OUTPUT, ofpact_output, ofpact, "output") \     OFPACT(GROUP, ofpact_group, ofpact, "group") \     OFPACT(CONTROLLER, ofpact_controller, ofpact, "controller") \     OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \     OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \     OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \                                                                         \     /* Header changes. */ \     OFPACT(SET_FIELD, ofpact_set_field, ofpact, "set_field") \     OFPACT(HANDLE_EXAMPLE, ofpact_null, ofpact, "handle_example") \     OFPACT(SET_VLAN_VID, ofpact_vlan_vid, ofpact, "set_vlan_vid") \     OFPACT(SET_VLAN_PCP, ofpact_vlan_pcp, ofpact, "set_vlan_pcp") \     OFPACT(STRIP_VLAN, ofpact_null, ofpact, "strip_vlan") \     OFPACT(PUSH_VLAN, ofpact_null, ofpact, "push_vlan") \     OFPACT(SET_ETH_SRC, ofpact_mac, ofpact, "mod_dl_src") \     OFPACT(SET_ETH_DST, ofpact_mac, ofpact, "mod_dl_dst") \     OFPACT(SET_IPV4_SRC, ofpact_ipv4, ofpact, "mod_nw_src") \     OFPACT(SET_IPV4_DST, ofpact_ipv4, ofpact, "mod_nw_dst") \     OFPACT(SET_IP_DSCP, ofpact_dscp, ofpact, "mod_nw_tos") \     OFPACT(SET_IP_ECN, ofpact_ecn, ofpact, "mod_nw_ecn") \     OFPACT(SET_IP_TTL, ofpact_ip_ttl, ofpact, "mod_nw_ttl") \     OFPACT(SET_L4_SRC_PORT, ofpact_l4_port, ofpact, "mod_tp_src") \     OFPACT(SET_L4_DST_PORT, ofpact_l4_port, ofpact, "mod_tp_dst") \     OFPACT(REG_MOVE, ofpact_reg_move, ofpact, "move") \     OFPACT(STACK_PUSH, ofpact_stack, ofpact, "push") \     OFPACT(STACK_POP, ofpact_stack, ofpact, "pop") \     OFPACT(DEC_TTL, ofpact_cnt_ids, cnt_ids, "dec_ttl") \     OFPACT(SET_MPLS_LABEL, ofpact_mpls_label, ofpact, "set_mpls_label") \     OFPACT(SET_MPLS_TC, ofpact_mpls_tc, ofpact, "set_mpls_tc") \     OFPACT(SET_MPLS_TTL, ofpact_mpls_ttl, ofpact, "set_mpls_ttl") \     OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact, "dec_mpls_ttl") \     OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact, "push_mpls") \     OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact, "pop_mpls") \                                                                         \     /* Metadata. */ \     OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact, "set_tunnel") \     OFPACT(SET_QUEUE, ofpact_queue, ofpact, "set_queue") \     OFPACT(POP_QUEUE, ofpact_null, ofpact, "pop_queue") \     OFPACT(FIN_TIMEOUT, ofpact_fin_timeout, ofpact, "fin_timeout") \                                                                         \     /* Flow table interaction. */ \     OFPACT(RESUBMIT, ofpact_resubmit, ofpact, "resubmit") \     OFPACT(LEARN, ofpact_learn, specs, "learn") \     OFPACT(CONJUNCTION, ofpact_conjunction, ofpact, "conjunction") \                                                                         \     /* Arithmetic. */ \     OFPACT(MULTIPATH, ofpact_multipath, ofpact, "multipath") \                                                                         \     /* Other. */ \     OFPACT(NOTE, ofpact_note, data, "note") \     OFPACT(EXIT, ofpact_null, ofpact, "exit") \     OFPACT(SAMPLE, ofpact_sample, ofpact, "sample") \     OFPACT(UNROLL_XLATE, ofpact_unroll_xlate, ofpact, "unroll_xlate") \     OFPACT(CT, ofpact_conntrack, ofpact, "ct") \                                                                         \     /* Debugging actions. \      * \      * These are intentionally undocumented, subject to change, and \      * only accepted if ovs-vswitchd is started with --enable-dummy. */ \     OFPACT(DEBUG_RECIRC, ofpact_null, ofpact, "debug_recirc") \                                                                         \     /* Instructions. */ \     OFPACT(METER, ofpact_meter, ofpact, "meter") \     OFPACT(CLEAR_ACTIONS, ofpact_null, ofpact, "clear_actions") \     OFPACT(WRITE_ACTIONS, ofpact_nest, ofpact, "write_actions") \     OFPACT(WRITE_METADATA, ofpact_metadata, ofpact, "write_metadata") \     OFPACT(GOTO_TABLE, ofpact_goto_table, ofpact, "goto_table")

 

第三、修改ofproto\ofproto-dpif-xlate.c文件

 

staticvoid recirc_unroll_actions(conststruct ofpact *ofpacts, size_t ofpacts_len,                       struct xlate_ctx *ctx) {     conststruct ofpact *a;       OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {         switch (a->type) {         case OFPACT_OPERATE_EXAMPLE:             /* These may not generate PACKET INs. */             break;

 

staticvoid do_xlate_actions(conststruct ofpact *ofpacts, size_t ofpacts_len,                  struct xlate_ctx *ctx) {     struct flow_wildcards *wc = ctx->wc;     struct flow *flow = &ctx->xin->flow;     conststruct ofpact *a;       if (ovs_native_tunneling_is_on(ctx->xbridge->ofproto)) {         tnl_neigh_snoop(flow, wc, ctx->xbridge->name);     }     /* dl_type already in the mask, not set below. */       OFPACT_FOR_EACH (a, ofpacts, ofpacts_len) {         struct ofpact_controller *controller;         conststruct ofpact_metadata *metadata;         conststruct ofpact_set_field *set_field;         conststruct mf_field *mf;           if (ctx->error) {             break;         }           if (ctx->exit) {             /* Check if need to store the remaining actions for later              * execution. */             if (exit_recirculates(ctx)) {                 recirc_unroll_actions(a, OFPACT_ALIGN(ofpacts_len -                                                       ((uint8_t *)a -                                                        (uint8_t *)ofpacts)),                                       ctx);             }             break;         }           switch (a->type) {    case OFPACT_HANDLE_EXAMPLE:             VLOG_INFO("OFPACT_HANDLE_EXAMPLE");             CHECK_MPLS_RECIRCULATION();             handle_example(flow, wc, ctx->xin->packet, ctx);             break;

 

最最重要的就是handle_example的实现,为你自己实现的逻辑,对于包头的修改可以通过修改flow来进行,也可以进一步解析ctx->xin->packet,也即解析网络包的正文。

转载请注明原文地址: https://www.6miu.com/read-34635.html

最新回复(0)