Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef NETD_SERVER_TRAFFIC_CONTROLLER_H
     18 #define NETD_SERVER_TRAFFIC_CONTROLLER_H
     19 
     20 #include <linux/bpf.h>
     21 
     22 #include <netdutils/StatusOr.h>
     23 #include "FirewallController.h"
     24 #include "NetlinkListener.h"
     25 #include "Network.h"
     26 #include "android-base/thread_annotations.h"
     27 #include "android-base/unique_fd.h"
     28 #include "bpf/BpfMap.h"
     29 
     30 using android::bpf::BpfMap;
     31 using android::bpf::IfaceValue;
     32 using android::bpf::StatsKey;
     33 using android::bpf::StatsValue;
     34 using android::bpf::UidTag;
     35 
     36 namespace android {
     37 namespace net {
     38 
     39 class DumpWriter;
     40 
     41 class TrafficController {
     42   public:
     43     TrafficController();
     44     /*
     45      * Initialize the whole controller
     46      */
     47     netdutils::Status start();
     48     /*
     49      * Tag the socket with the specified tag and uid. In the qtaguid module, the
     50      * first tag request that grab the spinlock of rb_tree can update the tag
     51      * information first and other request need to wait until it finish. All the
     52      * tag request will be addressed in the order of they obtaining the spinlock.
     53      * In the eBPF implementation, the kernel will try to update the eBPF map
     54      * entry with the tag request. And the hashmap update process is protected by
     55      * the spinlock initialized with the map. So the behavior of two modules
     56      * should be the same. No additional lock needed.
     57      */
     58     int tagSocket(int sockFd, uint32_t tag, uid_t uid);
     59 
     60     /*
     61      * The untag process is similiar to tag socket and both old qtaguid module and
     62      * new eBPF module have spinlock inside the kernel for concurrent update. No
     63      * external lock is required.
     64      */
     65     int untagSocket(int sockFd);
     66 
     67     /*
     68      * Similiar as above, no external lock required.
     69      */
     70     int setCounterSet(int counterSetNum, uid_t uid);
     71 
     72     /*
     73      * When deleting a tag data, the qtaguid module will grab the spinlock of each
     74      * related rb_tree one by one and delete the tag information, counterSet
     75      * information, iface stats information and uid stats information one by one.
     76      * The new eBPF implementation is done similiarly by removing the entry on
     77      * each map one by one. And deleting processes are also protected by the
     78      * spinlock of the map. So no additional lock is required.
     79      */
     80     int deleteTagData(uint32_t tag, uid_t uid);
     81 
     82     /*
     83      * Check if the current device have the bpf traffic stats accounting service
     84      * running.
     85      */
     86     bool checkBpfStatsEnable();
     87 
     88     /*
     89      * Add the interface name and index pair into the eBPF map.
     90      */
     91     int addInterface(const char* name, uint32_t ifaceIndex);
     92 
     93     int changeUidOwnerRule(ChildChain chain, const uid_t uid, FirewallRule rule, FirewallType type);
     94 
     95     int removeUidOwnerRule(const uid_t uid);
     96 
     97     int replaceUidOwnerMap(const std::string& name, bool isWhitelist,
     98                            const std::vector<int32_t>& uids);
     99 
    100     netdutils::Status updateOwnerMapEntry(BpfMap<uint32_t, uint8_t>& map, uid_t uid,
    101                                           FirewallRule rule, FirewallType type);
    102 
    103     void dump(DumpWriter& dw, bool verbose);
    104 
    105     netdutils::Status replaceUidsInMap(BpfMap<uint32_t, uint8_t>& map,
    106                                        const std::vector<int32_t>& uids, FirewallRule rule,
    107                                        FirewallType type);
    108 
    109     static const String16 DUMP_KEYWORD;
    110 
    111     int toggleUidOwnerMap(ChildChain chain, bool enable);
    112 
    113   private:
    114     /*
    115      * mCookieTagMap: Store the corresponding tag and uid for a specific socket.
    116      * DO NOT hold any locks when modifying this map, otherwise when the untag
    117      * operation is waiting for a lock hold by other process and there are more
    118      * sockets being closed than can fit in the socket buffer of the netlink socket
    119      * that receives them, then the kernel will drop some of these sockets and we
    120      * won't delete their tags.
    121      * Map Key: uint64_t socket cookie
    122      * Map Value: struct UidTag, contains a uint32 uid and a uint32 tag.
    123      */
    124     BpfMap<uint64_t, UidTag> mCookieTagMap;
    125 
    126     /*
    127      * mUidCounterSetMap: Store the counterSet of a specific uid.
    128      * Map Key: uint32 uid.
    129      * Map Value: uint32 counterSet specifies if the traffic is a background
    130      * or foreground traffic.
    131      */
    132     BpfMap<uint32_t, uint8_t> mUidCounterSetMap;
    133 
    134     /*
    135      * mAppUidStatsMap: Store the total traffic stats for a uid regardless of
    136      * tag, counterSet and iface. The stats is used by TrafficStats.getUidStats
    137      * API to return persistent stats for a specific uid since device boot.
    138      */
    139     BpfMap<uint32_t, StatsValue> mAppUidStatsMap;
    140 
    141     /*
    142      * mUidStatsMap: Store the traffic statistics for a specific combination of
    143      * uid, iface and counterSet. We maintain this map in addition to
    144      * mTagStatsMap because we want to be able to track per-UID data usage even
    145      * if mTagStatsMap is full.
    146      * Map Key: Struct StatsKey contains the uid, counterSet and ifaceIndex
    147      * information. The Tag in the StatsKey should always be 0.
    148      * Map Value: struct Stats, contains packet count and byte count of each
    149      * transport protocol on egress and ingress direction.
    150      */
    151     BpfMap<StatsKey, StatsValue> mUidStatsMap;
    152 
    153     /*
    154      * mTagStatsMap: Store the traffic statistics for a specific combination of
    155      * uid, tag, iface and counterSet. Only tagged socket stats should be stored
    156      * in this map.
    157      * Map Key: Struct StatsKey contains the uid, counterSet and ifaceIndex
    158      * information. The tag field should not be 0.
    159      * Map Value: struct Stats, contains packet count and byte count of each
    160      * transport protocol on egress and ingress direction.
    161      */
    162     BpfMap<StatsKey, StatsValue> mTagStatsMap;
    163 
    164     /*
    165      * mIfaceIndexNameMap: Store the index name pair of each interface show up
    166      * on the device since boot. The interface index is used by the eBPF program
    167      * to correctly match the iface name when receiving a packet.
    168      */
    169     BpfMap<uint32_t, IfaceValue> mIfaceIndexNameMap;
    170 
    171     /*
    172      * mIfaceStataMap: Store per iface traffic stats gathered from xt_bpf
    173      * filter.
    174      */
    175     BpfMap<uint32_t, StatsValue> mIfaceStatsMap;
    176 
    177     /*
    178      * mDozableUidMap: Store uids that have related rules in dozable mode owner match
    179      * chain.
    180      */
    181     BpfMap<uint32_t, uint8_t> mDozableUidMap GUARDED_BY(mOwnerMatchMutex);
    182 
    183     /*
    184      * mStandbyUidMap: Store uids that have related rules in standby mode owner match
    185      * chain.
    186      */
    187     BpfMap<uint32_t, uint8_t> mStandbyUidMap GUARDED_BY(mOwnerMatchMutex);
    188 
    189     /*
    190      * mPowerSaveUidMap: Store uids that have related rules in power save mode owner match
    191      * chain.
    192      */
    193     BpfMap<uint32_t, uint8_t> mPowerSaveUidMap GUARDED_BY(mOwnerMatchMutex);
    194 
    195     std::unique_ptr<NetlinkListenerInterface> mSkDestroyListener;
    196 
    197     bool ebpfSupported;
    198 
    199     std::mutex mOwnerMatchMutex;
    200 
    201     netdutils::Status loadAndAttachProgram(bpf_attach_type type, const char* path, const char* name,
    202                                            base::unique_fd& cg_fd);
    203 
    204     netdutils::Status initMaps();
    205     // For testing
    206     friend class TrafficControllerTest;
    207 };
    208 
    209 }  // namespace net
    210 }  // namespace android
    211 
    212 #endif  // NETD_SERVER_TRAFFIC_CONTROLLER_H
    213