diff --git a/include/linux/openvswitch.h b/include/linux/openvswitch.h index e09ed2b2f..e69fed4b7 100644 --- a/include/linux/openvswitch.h +++ b/include/linux/openvswitch.h @@ -202,6 +202,11 @@ enum ovs_packet_cmd { * @OVS_PACKET_ATTR_LEN: Packet size before truncation. * %OVS_PACKET_ATTR_USERSPACE action specify the Maximum received fragment * size. + * @OVS_PACKET_ATTR_UPCALL_PID: Netlink PID to use for upcalls while + * processing %OVS_PACKET_CMD_EXECUTE. Takes precedence over all other ways + * to determine the Netlink PID including %OVS_USERSPACE_ATTR_PID, + * %OVS_DP_ATTR_UPCALL_PID, %OVS_DP_ATTR_PER_CPU_PIDS and the + * %OVS_VPORT_ATTR_UPCALL_PID. * * These attributes follow the &struct ovs_header within the Generic Netlink * payload for %OVS_PACKET_* commands. @@ -221,6 +226,7 @@ enum ovs_packet_attr { OVS_PACKET_ATTR_MRU, /* Maximum received IP fragment size. */ OVS_PACKET_ATTR_LEN, /* Packet size before truncation. */ OVS_PACKET_ATTR_HASH, /* Packet hash. */ + OVS_PACKET_ATTR_UPCALL_PID, /* u32 Netlink PID. */ __OVS_PACKET_ATTR_MAX }; diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index f8850181d..7587c9c3e 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -2021,6 +2021,10 @@ dpif_netlink_encode_execute(int dp_ifindex, const struct dpif_execute *d_exec, if (d_exec->hash) { nl_msg_put_u64(buf, OVS_PACKET_ATTR_HASH, d_exec->hash); } + + if (d_exec->upcall_pid) { + nl_msg_put_u32(buf, OVS_PACKET_ATTR_UPCALL_PID, d_exec->upcall_pid); + } } /* Executes, against 'dpif', up to the first 'n_ops' operations in 'ops'. @@ -2987,6 +2991,7 @@ dpif_netlink_recv_windows(struct dpif_netlink *dpif, uint32_t handler_id, error = parse_odp_packet(buf, upcall, &dp_ifindex); if (!error && dp_ifindex == dpif->dp_ifindex) { + upcall->pid = 0; return 0; } else if (error) { return error; @@ -3037,6 +3042,7 @@ dpif_netlink_recv_cpu_dispatch(struct dpif_netlink *dpif, uint32_t handler_id, error = parse_odp_packet(buf, upcall, &dp_ifindex); if (!error && dp_ifindex == dpif->dp_ifindex) { + upcall->pid = nl_sock_pid(handler->sock); return 0; } else if (error) { return error; @@ -3113,6 +3119,7 @@ dpif_netlink_recv_vport_dispatch(struct dpif_netlink *dpif, error = parse_odp_packet(buf, upcall, &dp_ifindex); if (!error && dp_ifindex == dpif->dp_ifindex) { + upcall->pid = nl_sock_pid(ch->sock); return 0; } else if (error) { return error; diff --git a/lib/dpif.h b/lib/dpif.h index 6bef7d5b3..0b685d8df 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -732,6 +732,8 @@ struct dpif_execute { unsigned int mtu; /* Maximum transmission unit to fragment. 0 if not a fragmented packet */ uint64_t hash; /* Packet flow hash. 0 if not specified. */ + uint64_t upcall_pid; /* Netlink PID to use for upcalls. + * 0 if not specified. */ const struct flow *flow; /* Flow extracted from 'packet'. */ /* Input, but possibly modified as a side effect of execution. */ @@ -833,6 +835,7 @@ struct dpif_upcall { struct nlattr *mru; /* Maximum receive unit. */ struct nlattr *hash; /* Packet hash. */ struct nlattr *cutlen; /* Number of bytes shrink from the end. */ + uint32_t pid; /* Socket PID the upcall was received from. */ /* DPIF_UC_ACTION only. */ struct nlattr *userdata; /* Argument to OVS_ACTION_ATTR_USERSPACE. */ diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 53e59580d..9dfa52d82 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -230,6 +230,8 @@ struct upcall { uint16_t mru; /* If !0, Maximum receive unit of fragmented IP packet */ uint64_t hash; + uint32_t pid; /* Socket PID this upcall was received from, + * or zero. */ enum upcall_type type; /* Type of the upcall. */ const struct nlattr *actions; /* Flow actions in DPIF_UC_ACTION Upcalls. */ @@ -932,6 +934,7 @@ recv_upcalls(struct handler *handler) upcall->key_len = dupcall->key_len; upcall->ufid = &dupcall->ufid; upcall->hash = hash; + upcall->pid = dupcall->pid; upcall->out_tun_key = dupcall->out_tun_key; upcall->actions = dupcall->actions; @@ -1271,6 +1274,7 @@ upcall_receive(struct upcall *upcall, const struct dpif_backer *backer, upcall->key = NULL; upcall->key_len = 0; upcall->mru = mru; + upcall->pid = 0; upcall->out_tun_key = NULL; upcall->actions = NULL; @@ -1730,6 +1734,7 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls, op->dop.execute.probe = false; op->dop.execute.mtu = upcall->mru; op->dop.execute.hash = upcall->hash; + op->dop.execute.upcall_pid = upcall->pid; } }