Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef MPLS_INTERNAL_H
0003 #define MPLS_INTERNAL_H
0004 #include <net/mpls.h>
0005 
0006 /* put a reasonable limit on the number of labels
0007  * we will accept from userspace
0008  */
0009 #define MAX_NEW_LABELS 30
0010 
0011 struct mpls_entry_decoded {
0012     u32 label;
0013     u8 ttl;
0014     u8 tc;
0015     u8 bos;
0016 };
0017 
0018 struct mpls_pcpu_stats {
0019     struct mpls_link_stats  stats;
0020     struct u64_stats_sync   syncp;
0021 };
0022 
0023 struct mpls_dev {
0024     int             input_enabled;
0025     struct net_device       *dev;
0026     struct mpls_pcpu_stats __percpu *stats;
0027 
0028     struct ctl_table_header     *sysctl;
0029     struct rcu_head         rcu;
0030 };
0031 
0032 #if BITS_PER_LONG == 32
0033 
0034 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)      \
0035     do {                                \
0036         __typeof__(*(mdev)->stats) *ptr =           \
0037             raw_cpu_ptr((mdev)->stats);         \
0038         local_bh_disable();                 \
0039         u64_stats_update_begin(&ptr->syncp);            \
0040         ptr->stats.pkts_field++;                \
0041         ptr->stats.bytes_field += (len);            \
0042         u64_stats_update_end(&ptr->syncp);          \
0043         local_bh_enable();                  \
0044     } while (0)
0045 
0046 #define MPLS_INC_STATS(mdev, field)                 \
0047     do {                                \
0048         __typeof__(*(mdev)->stats) *ptr =           \
0049             raw_cpu_ptr((mdev)->stats);         \
0050         local_bh_disable();                 \
0051         u64_stats_update_begin(&ptr->syncp);            \
0052         ptr->stats.field++;                 \
0053         u64_stats_update_end(&ptr->syncp);          \
0054         local_bh_enable();                  \
0055     } while (0)
0056 
0057 #else
0058 
0059 #define MPLS_INC_STATS_LEN(mdev, len, pkts_field, bytes_field)      \
0060     do {                                \
0061         this_cpu_inc((mdev)->stats->stats.pkts_field);      \
0062         this_cpu_add((mdev)->stats->stats.bytes_field, (len));  \
0063     } while (0)
0064 
0065 #define MPLS_INC_STATS(mdev, field)         \
0066     this_cpu_inc((mdev)->stats->stats.field)
0067 
0068 #endif
0069 
0070 struct sk_buff;
0071 
0072 #define LABEL_NOT_SPECIFIED (1 << 20)
0073 
0074 /* This maximum ha length copied from the definition of struct neighbour */
0075 #define VIA_ALEN_ALIGN sizeof(unsigned long)
0076 #define MAX_VIA_ALEN (ALIGN(MAX_ADDR_LEN, VIA_ALEN_ALIGN))
0077 
0078 enum mpls_payload_type {
0079     MPT_UNSPEC, /* IPv4 or IPv6 */
0080     MPT_IPV4 = 4,
0081     MPT_IPV6 = 6,
0082 
0083     /* Other types not implemented:
0084      *  - Pseudo-wire with or without control word (RFC4385)
0085      *  - GAL (RFC5586)
0086      */
0087 };
0088 
0089 struct mpls_nh { /* next hop label forwarding entry */
0090     struct net_device   *nh_dev;
0091 
0092     /* nh_flags is accessed under RCU in the packet path; it is
0093      * modified handling netdev events with rtnl lock held
0094      */
0095     unsigned int        nh_flags;
0096     u8          nh_labels;
0097     u8          nh_via_alen;
0098     u8          nh_via_table;
0099     u8          nh_reserved1;
0100 
0101     u32         nh_label[];
0102 };
0103 
0104 /* offset of via from beginning of mpls_nh */
0105 #define MPLS_NH_VIA_OFF(num_labels) \
0106         ALIGN(sizeof(struct mpls_nh) + (num_labels) * sizeof(u32), \
0107               VIA_ALEN_ALIGN)
0108 
0109 /* all nexthops within a route have the same size based on the
0110  * max number of labels and max via length across all nexthops
0111  */
0112 #define MPLS_NH_SIZE(num_labels, max_via_alen)      \
0113         (MPLS_NH_VIA_OFF((num_labels)) +    \
0114         ALIGN((max_via_alen), VIA_ALEN_ALIGN))
0115 
0116 enum mpls_ttl_propagation {
0117     MPLS_TTL_PROP_DEFAULT,
0118     MPLS_TTL_PROP_ENABLED,
0119     MPLS_TTL_PROP_DISABLED,
0120 };
0121 
0122 /* The route, nexthops and vias are stored together in the same memory
0123  * block:
0124  *
0125  * +----------------------+
0126  * | mpls_route           |
0127  * +----------------------+
0128  * | mpls_nh 0            |
0129  * +----------------------+
0130  * | alignment padding    |   4 bytes for odd number of labels
0131  * +----------------------+
0132  * | via[rt_max_alen] 0   |
0133  * +----------------------+
0134  * | alignment padding    |   via's aligned on sizeof(unsigned long)
0135  * +----------------------+
0136  * | ...                  |
0137  * +----------------------+
0138  * | mpls_nh n-1          |
0139  * +----------------------+
0140  * | via[rt_max_alen] n-1 |
0141  * +----------------------+
0142  */
0143 struct mpls_route { /* next hop label forwarding entry */
0144     struct rcu_head     rt_rcu;
0145     u8          rt_protocol;
0146     u8          rt_payload_type;
0147     u8          rt_max_alen;
0148     u8          rt_ttl_propagate;
0149     u8          rt_nhn;
0150     /* rt_nhn_alive is accessed under RCU in the packet path; it
0151      * is modified handling netdev events with rtnl lock held
0152      */
0153     u8          rt_nhn_alive;
0154     u8          rt_nh_size;
0155     u8          rt_via_offset;
0156     u8          rt_reserved1;
0157     struct mpls_nh      rt_nh[];
0158 };
0159 
0160 #define for_nexthops(rt) {                      \
0161     int nhsel; const struct mpls_nh *nh;                \
0162     for (nhsel = 0, nh = (rt)->rt_nh;               \
0163          nhsel < (rt)->rt_nhn;                  \
0164          nh = (void *)nh + (rt)->rt_nh_size, nhsel++)
0165 
0166 #define change_nexthops(rt) {                       \
0167     int nhsel; struct mpls_nh *nh;                  \
0168     for (nhsel = 0, nh = (rt)->rt_nh;               \
0169          nhsel < (rt)->rt_nhn;                  \
0170          nh = (void *)nh + (rt)->rt_nh_size, nhsel++)
0171 
0172 #define endfor_nexthops(rt) }
0173 
0174 static inline struct mpls_entry_decoded mpls_entry_decode(struct mpls_shim_hdr *hdr)
0175 {
0176     struct mpls_entry_decoded result;
0177     unsigned entry = be32_to_cpu(hdr->label_stack_entry);
0178 
0179     result.label = (entry & MPLS_LS_LABEL_MASK) >> MPLS_LS_LABEL_SHIFT;
0180     result.ttl = (entry & MPLS_LS_TTL_MASK) >> MPLS_LS_TTL_SHIFT;
0181     result.tc =  (entry & MPLS_LS_TC_MASK) >> MPLS_LS_TC_SHIFT;
0182     result.bos = (entry & MPLS_LS_S_MASK) >> MPLS_LS_S_SHIFT;
0183 
0184     return result;
0185 }
0186 
0187 static inline struct mpls_dev *mpls_dev_get(const struct net_device *dev)
0188 {
0189     return rcu_dereference_rtnl(dev->mpls_ptr);
0190 }
0191 
0192 int nla_put_labels(struct sk_buff *skb, int attrtype,  u8 labels,
0193            const u32 label[]);
0194 int nla_get_labels(const struct nlattr *nla, u8 max_labels, u8 *labels,
0195            u32 label[], struct netlink_ext_ack *extack);
0196 bool mpls_output_possible(const struct net_device *dev);
0197 unsigned int mpls_dev_mtu(const struct net_device *dev);
0198 bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu);
0199 void mpls_stats_inc_outucastpkts(struct net_device *dev,
0200                  const struct sk_buff *skb);
0201 
0202 #endif /* MPLS_INTERNAL_H */