zoukankan      html  css  js  c++  java
  • openvswitch datapath 内核态流表创建过程(ovs_flow_cmd_new)

    datapath流表更新的入口函数都定义在dp_flow_genl_ops中,流表创建的入口函数是ovs_flow_cmd_new函数,通过该函数,我们可以一窥流表相关信息的建立。

    1、ovs_flow_cmd_new函数

      1 static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
      2 {
      3     struct net *net = sock_net(skb->sk);
      4     struct nlattr **a = info->attrs;
      5     struct ovs_header *ovs_header = info->userhdr;
      6     struct sw_flow *flow = NULL, *new_flow;
      7     struct sw_flow_mask mask;
      8     struct sk_buff *reply;
      9     struct datapath *dp;
     10     struct sw_flow_actions *acts;
     11     struct sw_flow_match match;
     12     u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
     13     int error;
     14     bool log = !a[OVS_FLOW_ATTR_PROBE];
     15 
     16     /* Must have key and actions. */
     17     error = -EINVAL;
     18     if (!a[OVS_FLOW_ATTR_KEY]) {
     19         OVS_NLERR(log, "Flow key attr not present in new flow.");
     20         goto error;
     21     }
     22     if (!a[OVS_FLOW_ATTR_ACTIONS]) {
     23         OVS_NLERR(log, "Flow actions attr not present in new flow.");
     24         goto error;
     25     }
     26 
     27     /* Most of the time we need to allocate a new flow, do it before
     28      * locking.
     29      */
     30     new_flow = ovs_flow_alloc();
     31     if (IS_ERR(new_flow)) {
     32         error = PTR_ERR(new_flow);
     33         goto error;
     34     }
     35 
     36     /* Extract key. */
     37     ovs_match_init(&match, &new_flow->key, false, &mask);
     38     error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
     39                   a[OVS_FLOW_ATTR_MASK], log);
     40     if (error)
     41         goto err_kfree_flow;
     42 
     43     /* Extract flow identifier. */
     44     error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
     45                        &new_flow->key, log);
     46     if (error)
     47         goto err_kfree_flow;
     48 
     49     /* unmasked key is needed to match when ufid is not used. */
     50     if (ovs_identifier_is_key(&new_flow->id))
     51         match.key = new_flow->id.unmasked_key;
     52 
     53     ovs_flow_mask_key(&new_flow->key, &new_flow->key, true, &mask);
     54 
     55     /* Validate actions. */
     56     error = ovs_nla_copy_actions(net, a[OVS_FLOW_ATTR_ACTIONS],
     57                      &new_flow->key, &acts, log);
     58     if (error) {
     59         OVS_NLERR(log, "Flow actions may not be safe on all matching packets.");
     60         goto err_kfree_flow;
     61     }
     62 
     63     reply = ovs_flow_cmd_alloc_info(acts, &new_flow->id, info, false,
     64                     ufid_flags);
     65     if (IS_ERR(reply)) {
     66         error = PTR_ERR(reply);
     67         goto err_kfree_acts;
     68     }
     69 
     70     ovs_lock();
     71     dp = get_dp(net, ovs_header->dp_ifindex);
     72     if (unlikely(!dp)) {
     73         error = -ENODEV;
     74         goto err_unlock_ovs;
     75     }
     76 
     77     /* Check if this is a duplicate flow */
     78     if (ovs_identifier_is_ufid(&new_flow->id))
     79         flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
     80     if (!flow)
     81         flow = ovs_flow_tbl_lookup(&dp->table, &new_flow->key);
     82     if (likely(!flow)) {
     83         rcu_assign_pointer(new_flow->sf_acts, acts);
     84 
     85         /* Put flow in bucket. */
     86         error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask);
     87         if (unlikely(error)) {
     88             acts = NULL;
     89             goto err_unlock_ovs;
     90         }
     91 
     92         if (unlikely(reply)) {
     93             error = ovs_flow_cmd_fill_info(new_flow,
     94                                ovs_header->dp_ifindex,
     95                                reply, info->snd_portid,
     96                                info->snd_seq, 0,
     97                                OVS_FLOW_CMD_NEW,
     98                                ufid_flags);
     99             BUG_ON(error < 0);
    100         }
    101         ovs_unlock();
    102     } else {
    103         struct sw_flow_actions *old_acts;
    104 
    105         /* Bail out if we're not allowed to modify an existing flow.
    106          * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL
    107          * because Generic Netlink treats the latter as a dump
    108          * request.  We also accept NLM_F_EXCL in case that bug ever
    109          * gets fixed.
    110          */
    111         if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE
    112                              | NLM_F_EXCL))) {
    113             error = -EEXIST;
    114             goto err_unlock_ovs;
    115         }
    116         /* The flow identifier has to be the same for flow updates.
    117          * Look for any overlapping flow.
    118          */
    119         if (unlikely(!ovs_flow_cmp(flow, &match))) {
    120             if (ovs_identifier_is_key(&flow->id))
    121                 flow = ovs_flow_tbl_lookup_exact(&dp->table,
    122                                  &match);
    123             else /* UFID matches but key is different */
    124                 flow = NULL;
    125             if (!flow) {
    126                 error = -ENOENT;
    127                 goto err_unlock_ovs;
    128             }
    129         }
    130         /* Update actions. */
    131         old_acts = ovsl_dereference(flow->sf_acts);
    132         rcu_assign_pointer(flow->sf_acts, acts);
    133 
    134         if (unlikely(reply)) {
    135             error = ovs_flow_cmd_fill_info(flow,
    136                                ovs_header->dp_ifindex,
    137                                reply, info->snd_portid,
    138                                info->snd_seq, 0,
    139                                OVS_FLOW_CMD_NEW,
    140                                ufid_flags);
    141             BUG_ON(error < 0);
    142         }
    143         ovs_unlock();
    144 
    145         ovs_nla_free_flow_actions_rcu(old_acts);
    146         ovs_flow_free(new_flow, false);
    147     }
    148 
    149     if (reply)
    150         ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
    151     return 0;
    152 
    153 err_unlock_ovs:
    154     ovs_unlock();
    155     kfree_skb(reply);
    156 err_kfree_acts:
    157     ovs_nla_free_flow_actions(acts);
    158 err_kfree_flow:
    159     ovs_flow_free(new_flow, false);
    160 error:
    161     return error;
    162 }

    2、ovs_flow_tbl_insert函数

     1 /* Must be called with OVS mutex held. */
     2 int ovs_flow_tbl_insert(struct flow_table *table, struct sw_flow *flow,
     3             const struct sw_flow_mask *mask)
     4 {
     5     int err;
     6 
     7     err = flow_mask_insert(table, flow, mask);
     8     if (err)
     9         return err;
    10     flow_key_insert(table, flow);
    11     if (ovs_identifier_is_ufid(&flow->id))
    12         flow_ufid_insert(table, flow);
    13 
    14     return 0;
    15 }

    3、flow_mask_insert函数

     1 /* Add 'mask' into the mask list, if it is not already there. */
     2 static int flow_mask_insert(struct flow_table *tbl, struct sw_flow *flow,
     3                 const struct sw_flow_mask *new)
     4 {
     5     struct sw_flow_mask *mask;
     6 
     7     mask = flow_mask_find(tbl, new);
     8     if (!mask) {
     9         struct mask_array *ma;
    10         int i;
    11 
    12         /* Allocate a new mask if none exsits. */
    13         mask = mask_alloc();
    14         if (!mask)
    15             return -ENOMEM;
    16 
    17         mask->key = new->key;
    18         mask->range = new->range;
    19 
    20         /* Add mask to mask-list. */
    21         ma = ovsl_dereference(tbl->mask_array);
    22         if (ma->count >= ma->max) {
    23             int err;
    24 
    25             err = tbl_mask_array_realloc(tbl, ma->max +
    26                               MASK_ARRAY_SIZE_MIN);
    27             if (err) {
    28                 kfree(mask);
    29                 return err;
    30             }
    31             ma = ovsl_dereference(tbl->mask_array);
    32         }
    33 
    34         for (i = 0; i < ma->max; i++) {
    35             struct sw_flow_mask *t;
    36 
    37             t = ovsl_dereference(ma->masks[i]);
    38             if (!t) {
    39                 rcu_assign_pointer(ma->masks[i], mask);
    40                 ma->count++;
    41                 break;
    42             }
    43         }
    44 
    45     } else {
    46         BUG_ON(!mask->ref_count);
    47         mask->ref_count++;
    48     }
    49 
    50     flow->mask = mask;
    51     return 0;
    52 }

    4、flow_key_insert函数

     1 /* Must be called with OVS mutex held. */
     2 static void flow_key_insert(struct flow_table *table, struct sw_flow *flow)
     3 {
     4     struct table_instance *new_ti = NULL;
     5     struct table_instance *ti;
     6 
     7     flow->flow_table.hash = flow_hash(&flow->key, &flow->mask->range);
     8     ti = ovsl_dereference(table->ti);
     9     table_instance_insert(ti, flow);
    10     table->count++;
    11 
    12     /* Expand table, if necessary, to make room. */
    13     if (table->count > ti->n_buckets)
    14         new_ti = table_instance_expand(ti, false);
    15     else if (time_after(jiffies, table->last_rehash + REHASH_INTERVAL))
    16         new_ti = table_instance_rehash(ti, ti->n_buckets, false);
    17 
    18     if (new_ti) {
    19         rcu_assign_pointer(table->ti, new_ti);
    20         call_rcu(&ti->rcu, flow_tbl_destroy_rcu_cb);
    21         table->last_rehash = jiffies;
    22     }
    23 }

    5、table_instance_insert函数

    1 static void table_instance_insert(struct table_instance *ti,
    2                   struct sw_flow *flow)
    3 {
    4     struct hlist_head *head;
    5 
    6     head = find_bucket(ti, flow->flow_table.hash);
    7     hlist_add_head_rcu(&flow->flow_table.node[ti->node_ver], head);
    8 }

     6、ovs_nla_copy_actions函数

     1 /* 'key' must be the masked key. */
     2 int ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
     3              const struct sw_flow_key *key,
     4              struct sw_flow_actions **sfa, bool log)
     5 {
     6     int err;
     7 
     8     *sfa = nla_alloc_flow_actions(min(nla_len(attr), MAX_ACTIONS_BUFSIZE));
     9     if (IS_ERR(*sfa))
    10         return PTR_ERR(*sfa);
    11 
    12     (*sfa)->orig_len = nla_len(attr);
    13     err = __ovs_nla_copy_actions(net, attr, key, sfa, key->eth.type,
    14                      key->eth.vlan.tci, log);
    15     if (err)
    16         ovs_nla_free_flow_actions(*sfa);
    17 
    18     return err;
    19 }

    7、__ovs_nla_copy_actions函数

      1 static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
      2                   const struct sw_flow_key *key,
      3                   struct sw_flow_actions **sfa,
      4                   __be16 eth_type, __be16 vlan_tci, bool log)
      5 {
      6     u8 mac_proto = ovs_key_mac_proto(key);
      7     const struct nlattr *a;
      8     int rem, err;
      9 
     10     nla_for_each_nested(a, attr, rem) {
     11         /* Expected argument lengths, (u32)-1 for variable length. */
     12         static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = {
     13             [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
     14             [OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
     15             [OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
     16             [OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
     17             [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
     18             [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
     19             [OVS_ACTION_ATTR_POP_VLAN] = 0,
     20             [OVS_ACTION_ATTR_SET] = (u32)-1,
     21             [OVS_ACTION_ATTR_SET_MASKED] = (u32)-1,
     22             [OVS_ACTION_ATTR_SAMPLE] = (u32)-1,
     23             [OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
     24             [OVS_ACTION_ATTR_CT] = (u32)-1,
     25             [OVS_ACTION_ATTR_CT_CLEAR] = 0,
     26             [OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
     27             [OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
     28             [OVS_ACTION_ATTR_POP_ETH] = 0,
     29             [OVS_ACTION_ATTR_PUSH_NSH] = (u32)-1,
     30             [OVS_ACTION_ATTR_POP_NSH] = 0,
     31         };
     32         const struct ovs_action_push_vlan *vlan;
     33         int type = nla_type(a);
     34         bool skip_copy;
     35 
     36         if (type > OVS_ACTION_ATTR_MAX ||
     37             (action_lens[type] != nla_len(a) &&
     38              action_lens[type] != (u32)-1))
     39             return -EINVAL;
     40 
     41         skip_copy = false;
     42         switch (type) {
     43         case OVS_ACTION_ATTR_UNSPEC:
     44             return -EINVAL;
     45 
     46         case OVS_ACTION_ATTR_USERSPACE:
     47             err = validate_userspace(a);
     48             if (err)
     49                 return err;
     50             break;
     51 
     52         case OVS_ACTION_ATTR_OUTPUT:
     53             if (nla_get_u32(a) >= DP_MAX_PORTS)
     54                 return -EINVAL;
     55             break;
     56 
     57         case OVS_ACTION_ATTR_TRUNC: {
     58             const struct ovs_action_trunc *trunc = nla_data(a);
     59 
     60             if (trunc->max_len < ETH_HLEN)
     61                 return -EINVAL;
     62             break;
     63         }
     64 
     65         case OVS_ACTION_ATTR_HASH: {
     66             const struct ovs_action_hash *act_hash = nla_data(a);
     67 
     68             switch (act_hash->hash_alg) {
     69             case OVS_HASH_ALG_L4:
     70                 break;
     71             default:
     72                 return  -EINVAL;
     73             }
     74 
     75             break;
     76         }
     77 
     78         case OVS_ACTION_ATTR_POP_VLAN:
     79             if (mac_proto != MAC_PROTO_ETHERNET)
     80                 return -EINVAL;
     81             vlan_tci = htons(0);
     82             break;
     83 
     84         case OVS_ACTION_ATTR_PUSH_VLAN:
     85             if (mac_proto != MAC_PROTO_ETHERNET)
     86                 return -EINVAL;
     87             vlan = nla_data(a);
     88             if (!eth_type_vlan(vlan->vlan_tpid))
     89                 return -EINVAL;
     90             if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT)))
     91                 return -EINVAL;
     92             vlan_tci = vlan->vlan_tci;
     93             break;
     94 
     95         case OVS_ACTION_ATTR_RECIRC:
     96             break;
     97 
     98         case OVS_ACTION_ATTR_PUSH_MPLS: {
     99             const struct ovs_action_push_mpls *mpls = nla_data(a);
    100 
    101             if (!eth_p_mpls(mpls->mpls_ethertype))
    102                 return -EINVAL;
    103             /* Prohibit push MPLS other than to a white list
    104              * for packets that have a known tag order.
    105              */
    106             if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
    107                 (eth_type != htons(ETH_P_IP) &&
    108                  eth_type != htons(ETH_P_IPV6) &&
    109                  eth_type != htons(ETH_P_ARP) &&
    110                  eth_type != htons(ETH_P_RARP) &&
    111                  !eth_p_mpls(eth_type)))
    112                 return -EINVAL;
    113             eth_type = mpls->mpls_ethertype;
    114             break;
    115         }
    116 
    117         case OVS_ACTION_ATTR_POP_MPLS:
    118             if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
    119                 !eth_p_mpls(eth_type))
    120                 return -EINVAL;
    121 
    122             /* Disallow subsequent L2.5+ set and mpls_pop actions
    123              * as there is no check here to ensure that the new
    124              * eth_type is valid and thus set actions could
    125              * write off the end of the packet or otherwise
    126              * corrupt it.
    127              *
    128              * Support for these actions is planned using packet
    129              * recirculation.
    130              */
    131             eth_type = htons(0);
    132             break;
    133 
    134         case OVS_ACTION_ATTR_SET:
    135             err = validate_set(a, key, sfa,
    136                        &skip_copy, mac_proto, eth_type,
    137                        false, log);
    138             if (err)
    139                 return err;
    140             break;
    141 
    142         case OVS_ACTION_ATTR_SET_MASKED:
    143             err = validate_set(a, key, sfa,
    144                        &skip_copy, mac_proto, eth_type,
    145                        true, log);
    146             if (err)
    147                 return err;
    148             break;
    149 
    150         case OVS_ACTION_ATTR_SAMPLE: {
    151             bool last = nla_is_last(a, rem);
    152 
    153             err = validate_and_copy_sample(net, a, key, sfa,
    154                                eth_type, vlan_tci,
    155                                log, last);
    156             if (err)
    157                 return err;
    158             skip_copy = true;
    159             break;
    160         }
    161 
    162         case OVS_ACTION_ATTR_CT:
    163             err = ovs_ct_copy_action(net, a, key, sfa, log);
    164             if (err)
    165                 return err;
    166             skip_copy = true;
    167             break;
    168 
    169         case OVS_ACTION_ATTR_CT_CLEAR:
    170             break;
    171 
    172         case OVS_ACTION_ATTR_PUSH_ETH:
    173             /* Disallow pushing an Ethernet header if one
    174              * is already present */
    175             if (mac_proto != MAC_PROTO_NONE)
    176                 return -EINVAL;
    177             mac_proto = MAC_PROTO_NONE;
    178             break;
    179 
    180         case OVS_ACTION_ATTR_POP_ETH:
    181             if (mac_proto != MAC_PROTO_ETHERNET)
    182                 return -EINVAL;
    183             if (vlan_tci & htons(VLAN_TAG_PRESENT))
    184                 return -EINVAL;
    185             mac_proto = MAC_PROTO_ETHERNET;
    186             break;
    187 
    188         case OVS_ACTION_ATTR_PUSH_NSH:
    189             if (mac_proto != MAC_PROTO_ETHERNET) {
    190                 u8 next_proto;
    191 
    192                 next_proto = tun_p_from_eth_p(eth_type);
    193                 if (!next_proto)
    194                     return -EINVAL;
    195             }
    196             mac_proto = MAC_PROTO_NONE;
    197             if (!validate_nsh(nla_data(a), false, true, true))
    198                 return -EINVAL;
    199             break;
    200 
    201         case OVS_ACTION_ATTR_POP_NSH: {
    202             __be16 inner_proto;
    203 
    204             if (eth_type != htons(ETH_P_NSH))
    205                 return -EINVAL;
    206             inner_proto = tun_p_to_eth_p(key->nsh.base.np);
    207             if (!inner_proto)
    208                 return -EINVAL;
    209             if (key->nsh.base.np == TUN_P_ETHERNET)
    210                 mac_proto = MAC_PROTO_ETHERNET;
    211             else
    212                 mac_proto = MAC_PROTO_NONE;
    213             break;
    214         }
    215 
    216         default:
    217             OVS_NLERR(log, "Unknown Action type %d", type);
    218             return -EINVAL;
    219         }
    220         if (!skip_copy) {
    221             err = copy_action(a, sfa, log);
    222             if (err)
    223                 return err;
    224         }
    225     }
    226 
    227     if (rem > 0)
    228         return -EINVAL;
    229 
    230     return 0;
    231 }

    调试信息:

    场景一:

    流表:
    ovs-ofctl add-flow aaa 'table=0, in_port=veth2 actions=push_mpls:0x8847,set_mpls_label:800,resubmit(,10)' -O openflow15
    ovs-ofctl add-flow aaa 'table=10, mpls, mpls_label=800 actions=pop_mpls:0x0800,mod_dl_src=fe:22:33:44:55:66,mod_dl_dst=11:22:33:44:55:66,output:veth3' -O openflow15
    
    调试信息:
    3月 20 16:18:30 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:18:30 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:18:30 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:18:30 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: do_execute_actions, type: 20
    3月 20 16:18:30 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_SET_TO_MASKED
    3月 20 16:18:30 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:18:30 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:18:30 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:18:30 localhost.localdomain kernel: queue_userspace_packet ... ...
    3月 20 16:18:30 localhost.localdomain kernel: ovs_flow_cmd_new ... ...

    场景二:

    流表:
    ovs-ofctl add-flow aaa 'table=0, in_port=veth2 actions=push_mpls:0x8847,set_mpls_label:800,output:veth3' -O openflow15
    ovs-ofctl add-flow aaa 'table=0, in_port=veth4, mpls, mpls_label=800 actions=pop_mpls:0x0800,mod_dl_src=fe:22:33:44:55:66,mod_dl_dst=11:22:33:44:55:66,output:veth5' -O openflow15
    
    调试信息:
    3月 20 16:30:27 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: type: 9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: type: 9, key_len=12796
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=-1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 9
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_PUSH_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:30:27 localhost.localdomain kernel: queue_userspace_packet ... ...
    3月 20 16:30:27 localhost.localdomain kernel: ovs_flow_cmd_new ... ...
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:30:27 localhost.localdomain kernel: type: 10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: nla_for_each_nested, type=1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: type: 3, key_len=12
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_SET
    3月 20 16:30:27 localhost.localdomain kernel: type: 10, key_len=4
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: type: 1, key_len=1
    3月 20 16:30:27 localhost.localdomain kernel: OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 20
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_SET_TO_MASKED
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 10
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_POP_MPLS
    3月 20 16:30:27 localhost.localdomain kernel: do_execute_actions, type: 1
    3月 20 16:30:27 localhost.localdomain kernel: kernel OVS_ACTION_ATTR_OUTPUT
    3月 20 16:30:27 localhost.localdomain kernel: not find ovs flows ... ...
    3月 20 16:30:27 localhost.localdomain kernel: queue_userspace_packet ... ...

    总结:

    以上以mpls封装解封装为例(或push_vlan,pop_vlan,push_nsh,pop_nsh,push_eth,pop_eth等)

    从场景一和场景二得出结论:

    流表从in到out中间的过程,如果同时存在push和pop动作,ovs会跳过push和pop动作的处理,不会copy到kernel的流表项中

  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/wangjq19920210/p/10564531.html
Copyright © 2011-2022 走看看