有时候我们需要自定义一些自己的action,根据包头里面的信息,做一些自己的操作。
例如添加一个action名为handle_example
首先在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;
#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")
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,也即解析网络包的正文。