2014년 12월 27일 토요일

[Linux Kernel] 84주차(2014.12.27)

ARM10C 84주차 후기

일시 : 2014.12.27 (84주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

84주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->combiner_init()
  • IRQ 설정과 동작과정을 알아봅니다.
  • spsr_irq , r0, 일반 모드 비법
  • Note movs: 명령을 PC에 사용할 때.ARM의 모드를 변경
  • Exception retrun)
  • SPSR_irq에 저장된 값을 CPSR로 로드함.
__irq_svc:
    svc_entry
  • .fnstart 함수의 시작.
  • (.save {r0 - pc})
    • Generate Unwinder
    • stack에 R0~PC까지저장.
    sub sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
  • S_FRAME_SIZE: 72, stack_hole: 0

log

  • 1st log
   1342489..78084c4  master     -> origin/master
Updating 1342489..78084c4
Fast-forward
"Reference/Cortex\342\204\242-A_Series_Programmer_Guide.pdf" | Bin 0 -> 4235851 bytes
arch/arm/include/asm/unified.h                               |   4 +++-
arch/arm/include/uapi/asm/ptrace.h                           |   6 +++++-
arch/arm/kernel/entry-armv.S                                 |  79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
arch/arm/kernel/setup.c                                      |   3 +++
5 files changed, 88 insertions(+), 4 deletions(-)
create mode 100644 "Reference/Cortex\342\204\242-A_Series_Programmer_Guide.pdf"
  • 2nd log
   78084c4..ca77f3b  master     -> origin/master
Updating 78084c4..ca77f3b
Fast-forward
arch/arm/include/asm/ptrace.h   |  1 +
arch/arm/include/asm/unified.h  |  3 +-
arch/arm/kernel/asm-offsets.c   |  4 ++
arch/arm/kernel/entry-armv.S    | 96 ++++++++++++++++++++++++++++++++++++++---
arch/arm/kernel/irq.c           |  8 ++++
drivers/irqchip/irq-gic.c       | 26 +++++++++++
include/asm-generic/current.h   |  1 +
include/asm-generic/irq_regs.h  | 11 +++++
include/asm-generic/preempt.h   |  6 +++
include/linux/compiler-gcc.h    |  1 +
include/linux/irqchip/arm-gic.h |  2 +
include/linux/irqflags.h        |  1 +
include/linux/preempt.h         |  1 +
include/linux/preempt_mask.h    |  8 ++++
include/linux/sched.h           |  4 ++
include/linux/smp.h             |  1 +
include/trace/events/rcu.h      |  1 +
kernel/irq/irqdomain.c          |  2 +
kernel/rcu/tree.c               | 25 ++++++++++-
kernel/rcu/tree.h               |  5 ++-
kernel/rcu/tree_plugin.h        |  1 +
kernel/sched/core.c             |  7 +++
kernel/softirq.c                | 28 +++++++++++-
23 files changed, 231 insertions(+), 12 deletions(-)

2014년 12월 25일 목요일

The Big Players of Orchestration for NFV

The Big Players of Orchestration for NFV

 Network functions virtualization (NFV) management and orchestration (MANO) is still early in development and will come to market slowly, but big vendors are ahead of the game in this market.

 About NFV, the battle for mind-share among industry bodies and the largest players in the network equipment provider, OSS and IT space. We focus How to the services built of virtualized network functions are managed through their lifecycle, and the ways that the biggest vendors are responding to the challenge of delivering NFV MANO platforms to support their customers.

 NFV orchestration is still at an early stage of development, with many vendors testing out their ideas with their customers, and developing concepts based on their existing network management, cloud management and operations support system (OSS) assets.


Key Issues.
  • ETSI has defined NFV orchestration, but the functionality must coexist with other functions and systems and within broader environments, and therein lies the scope for confusion
  • The choice of service and resource modeling language and tools is a differentiator
  • A layered approach separating service orchestration from resource orchestration is proposed by many equipment providers, OSS and IT vendors
  • Openness in orchestration means, at least in part, the ability to support multiple technology stacks
  • The drivers of NFV are still strong, but it is difficult to make the change to the OSS systems
  • The market is at an early stage of development with a range of maturity displayed by vendors, but big vendors are in a strong position
The Big Players of Orchestration for NFV
  • Alcatel-Lucent (NYSE: ALU)
  • Amdocs Inc. (Nasdaq: DOX)
  • Cisco Systems Inc. (NYSE: CSCO)
  • Ericsson AB (Nasdaq: ERIC)
  • Hewlett-Packard Corp. (NYSE: HPQ)
  • Huawei Technologies Co. Ltd.
  • IBM Corp. (NYSE: IBM)
  • Juniper Networks Inc. (NYSE: JNPR)
  • NetCracker Technologies, a wholly-owned subsidiary of NEC Corp. (TYO: 6701)
  • Nokia Networks, a division of Nokia Corp. (NYSE: NOK)
  • Oracle Corp. (NYSE: ORCL) 

2014년 12월 20일 토요일

[Linux Kernel] 83주차(2014.12.20)

ARM10C 83주차 후기

일시 : 2014.12.20 (83주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

83주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->combiner_init() a* of_irq_init()에서 2번째 루프인 combiner_init()을 진행합니다.

main.c::start_kernel()

asmlinkage void __init start_kernel(void)
{
...
    setup_arch(&command_line);
...
    mm_init();
    // buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
    // pcpu 메모리, vmlist 는 slab으로 이관
...
    rcu_init();
    // rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
...
    /* init some links before init_ISA_irqs() */
    early_irq_init();
    // irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
    // allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

    init_IRQ();
  • call: start_kernel()->init_IRQ()
    • init_IRQ();

irq.c::init_IRQ()

  • called: start_kernel()->init_IRQ()
    • init_IRQ();
// ARM10C 20141004
void __init init_IRQ(void)
{
    // CONFIG_OF=y, machine_desc->init_irq: __mach_desc_EXYNOS5_DT.init_irq: 0
    if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
        irqchip_init();
    else
        machine_desc->init_irq();
}
  • call: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();
// ARM10C 20141004
extern struct of_device_id __irqchip_begin[];

// ARM10C 20141004
void __init irqchip_init(void)
{
    // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    of_irq_init(__irqchip_begin);
}
#ifdef CONFIG_IRQCHIP // CONFIG_IRQCHIP=y
#define IRQCHIP_OF_MATCH_TABLE()            \
    . = ALIGN(8);                           \
    VMLINUX_SYMBOL(__irqchip_begin) = .;    \
    *(__irqchip_of_table)                   \
    *(__irqchip_of_end)
#else
#define IRQCHIP_OF_MATCH_TABLE()
#endif
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);
void __init of_irq_init(const struct of_device_id *matches)
{
    struct device_node *np, *parent = NULL;
    // parent: NULL
    struct intc_desc *desc, *temp_desc;
    struct list_head intc_desc_list, intc_parent_list;

    INIT_LIST_HEAD(&intc_desc_list);
    // intc_desc_list 리스트 초기화 수행

    INIT_LIST_HEAD(&intc_parent_list);
    // intc_parent_list 리스트 초기화 수행

    // matches: irqchip_of_match_exynos4210_combiner
    for_each_matching_node(np, matches) {
    // for (np = of_find_matching_node(NULL, matches); np; np = of_find_matching_node(np, matches))

        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, "interrupt-controller", NULL):
        // combiner node의 "interrupt-controller" property의 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, "interrupt-controller", NULL):
        // gic node의 "interrupt-controller" property의 주소
        if (!of_find_property(np, "interrupt-controller", NULL))
            continue;
        /*
         * Here, we allocate and populate an intc_desc with the node
         * pointer, interrupt-parent device_node etc.
         */
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o10
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o11
        desc = kzalloc(sizeof(*desc), GFP_KERNEL);
        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11

        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11
        if (WARN_ON(!desc))
            goto err;

        // desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        desc->dev = np;
        // desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소): gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소): gic node 주소
        desc->interrupt_parent = of_irq_find_parent(np);
        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        if (desc->interrupt_parent == np)
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
            desc->interrupt_parent = NULL;
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL

        // &desc->list: &(kmem_cache#30-o10)->list
        // &desc->list: &(kmem_cache#30-o11)->list
        list_add_tail(&desc->list, &intc_desc_list);
        // intc_desc_list에 (kmem_cache#30-o10)->list를 tail에 추가
        // intc_desc_list에 (kmem_cache#30-o11)->list를 tail에 추가
    }

    // irqchip_of_match_exynos4210_combiner, irqchip_of_match_cortex_a15_gic 의
    // struct intc_desc 메모리 할당, intc_desc 맴버가 초기화 된 값이 intc_desc_list list의 tail로 추가됨

    // list_empty(&intc_desc_list): 0
    while (!list_empty(&intc_desc_list)) {
        list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
        // for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
        //  temp_desc = list_next_entry(desc, list);
        //      &desc->list != (&intc_desc_list);
        //      desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))

            // desc: kmem_cache#30-o10 (exynos4210_combiner), temp_desc: kmem_cache#30-o11 (cortex_a15_gic)
            // desc: kmem_cache#30-o11 (cortex_a15_gic), temp_desc: NULL

            const struct of_device_id *match;
            int ret;
            of_irq_init_cb_t irq_init_cb;

            // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소, parent: NULL
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL, parent: NULL
            if (desc->interrupt_parent != parent)
                continue;
                // continue 수행 (exynos4210_combiner)

            // &desc->list: (kmem_cache#30-o11)->list
            list_del(&desc->list);
            // intc_desc_list에서 (kmem_cache#30-o11)->list를 삭제

            // matches: irqchip_of_match_cortex_a15_gic,
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // of_match_node(cortex_a15_gic, devtree에서 allnext로 순회 하면서 찾은 gic node의 주소):
            // irqchip_of_match_cortex_a15_gic
            match = of_match_node(matches, desc->dev);
            // match: irqchip_of_match_cortex_a15_gic

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            if (WARN(!match->data,
                "of_irq_init: no init function for %s\n",
                match->compatible)) {
                kfree(desc);
                continue;
            }

            // match->compatible: irqchip_of_match_cortex_a15_gic.compatible: "arm,cortex-a15-gic",
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            pr_debug("of_irq_init: init %s @ %p, parent %p\n",
                 match->compatible,
                 desc->dev, desc->interrupt_parent);
            // "of_irq_init: init arm,cortex-a15-gic @ 0x(gic node의 주소), parent 0\n"

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            irq_init_cb = (of_irq_init_cb_t)match->data;
            // irq_init_cb: gic_of_init

            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소,
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            // gic_of_init(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, NULL):
            ret = irq_init_cb(desc->dev, desc->interrupt_parent);

            // ret: 0
            if (ret) {
                kfree(desc);
                continue;
            }
            /*
             * This one is now set up; add it to the parent list so
             * its children can get processed in a subsequent pass.
             */
            // &desc->list: &(kmem_cache#30-o11)->list
            list_add_tail(&desc->list, &intc_parent_list);
            // intc_parent_list에 tail로 &(kmem_cache#30-o11)->list를 추가
        }
        // &desc->list: &intc_desc_list 이므로  loop 탈출

        /* Get the next pending parent that might have children */
        // typeof(*desc): struct intc_desc
        // list_first_entry_or_null(&intc_parent_list, struct intc_desc, list):
        // (!list_empty(&intc_parent_list) ? list_first_entry(&intc_parent_list, struct intc_desc, list) : NULL)
        // list_first_entry(&intc_parent_list, struct intc_desc, list): kmem_cache#30-o11 (cortex_a15_gic)
        desc = list_first_entry_or_null(&intc_parent_list,
                        typeof(*desc), list);
        // desc: kmem_cache#30-o11 (cortex_a15_gic)

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        if (!desc) {
            pr_err("of_irq_init: children remain, but no parents\n");
            break;
        }

        // &desc->list: &(kmem_cache#30-o11 (cortex_a15_gic))->list
        list_del(&desc->list);
        // &(kmem_cache#30-o11 (cortex_a15_gic))->list에 연결된 list 삭제

        // parent: NULL
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        parent = desc->dev;
        // parent: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        kfree(desc);

exynos-combiner.c::combiner_init()

// ARM10C 20141206
// combiner_base: 0xf0004000, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소,
// max_nr: 32, irq_base: 160
static void __init combiner_init(void __iomem *combiner_base,
                 struct device_node *np,
                 unsigned int max_nr,
                 int irq_base)
{
    int i, irq;
    unsigned int nr_irq;
    struct combiner_chip_data *combiner_data;

    // max_nr: 32, IRQ_IN_COMBINER: 8
    nr_irq = max_nr * IRQ_IN_COMBINER;
    // nr_irq: 256

    // max_nr: 32, sizeof(struct combiner_chip_data): 16 bytes, GFP_KERNEL: 0xD0
    // kcalloc(32, 16, GFP_KERNEL: 0xD0): kmem_cache#26-oX
    combiner_data = kcalloc(max_nr, sizeof (*combiner_data), GFP_KERNEL);
    // combiner_data: kmem_cache#26-oX

    // combiner_data: kmem_cache#26-oX
    if (!combiner_data) {
        pr_warning("%s: could not allocate combiner data\n", __func__);
        return;
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소,
    // nr_irq: 256, irq_base: 160, combiner_data: kmem_cache#26-oX
    // irq_domain_add_simple(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, 256
    // 160, &combiner_irq_domain_ops, kmem_cache#26-oX (combiner_data): kmem_cache#24-o0
    combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base,
                &combiner_irq_domain_ops, combiner_data);
    // combiner_irq_domain: kmem_cache#24-o0

    // irq_domain_add_simple에서 한일:
    // struct irq_domain를 위한 메모리 할당: kmem_cache#24-o0
    // (&(kmem_cache#24-o0)->revmap_tree)->height: 0
    // (&(kmem_cache#24-o0)->revmap_tree)->gfp_mask: (GFP_KERNEL: 0xD0)
    // (&(kmem_cache#24-o0)->revmap_tree)->rnode: NULL
    // (kmem_cache#24-o0)->ops: &combiner_irq_domain_ops
    // (kmem_cache#24-o0)->host_data: kmem_cache#26-oX (combiner_data)
    // (kmem_cache#24-o0)->of_node: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
    // (kmem_cache#24-o0)->hwirq_max: 256
    // (kmem_cache#24-o0)->revmap_size: 256
    // (kmem_cache#24-o0)->revmap_direct_max_irq: 0
    //
    // irq_domain_list에 (kmem_cache#24-o0)->link를 추가
    /*
    // struct irq_desc의 자료 구조크기 만큼 256개의 메모리를 할당 받아
    // radix tree 구조로 구성
    //
    // radix tree의 root node: &irq_desc_tree 값을 변경
    // (&irq_desc_tree)->rnode: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (&irq_desc_tree)->height: 2
    //
    // (kmem_cache#20-o1)->height: 2
    // (kmem_cache#20-o1)->count: 7
    // (kmem_cache#20-o1)->parent: NULL
    // (kmem_cache#20-o1)->slots[0]: kmem_cache#20-o0 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[1]: kmem_cache#20-o2 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[2]: kmem_cache#20-o3 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[3]: kmem_cache#20-o4 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[4]: kmem_cache#20-o5 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[5]: kmem_cache#20-o6 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[6]: kmem_cache#20-o7 (radix height 1 관리 주소)
    //
    // (kmem_cache#20-o0)->height: 1
    // (kmem_cache#20-o0)->count: 64
    // (kmem_cache#20-o0)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o0)->slots[0...63]: kmem_cache#28-oX (irq 0...63)
    //
    // (kmem_cache#20-o2)->height: 1
    // (kmem_cache#20-o2)->count: 64
    // (kmem_cache#20-o2)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o2)->slots[0...63]: kmem_cache#28-oX (irq 63...127)
    //
    // (kmem_cache#20-o3)->height: 1
    // (kmem_cache#20-o3)->count: 64
    // (kmem_cache#20-o3)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o3)->slots[0...63]: kmem_cache#28-oX (irq 127...191)
    //
    // (kmem_cache#20-o4)->height: 1
    // (kmem_cache#20-o4)->count: 64
    // (kmem_cache#20-o4)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o4)->slots[0...63]: kmem_cache#28-oX (irq 192...255)
    //
    // (kmem_cache#20-o5)->height: 1
    // (kmem_cache#20-o5)->count: 64
    // (kmem_cache#20-o5)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o5)->slots[0...63]: kmem_cache#28-oX (irq 256...319)
    //
    // (kmem_cache#20-o6)->height: 1
    // (kmem_cache#20-o6)->count: 64
    // (kmem_cache#20-o6)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o6)->slots[0...63]: kmem_cache#28-oX (irq 320...383)
    //
    // (kmem_cache#20-o7)->height: 1
    // (kmem_cache#20-o7)->count: 32
    // (kmem_cache#20-o7)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o7)->slots[0...31]: kmem_cache#28-oX (irq 384...415)
    //
    // (&irq_desc_tree)->rnode -->  +-----------------------+
    //                              |    radix_tree_node    |
    //                              |   (kmem_cache#20-o1)  |
    //                              +-----------------------+
    //                              | height: 2 | count: 7  |
    //                              +-----------------------+
    //                              | radix_tree_node 0 ~ 6 | \
    //                            / +-----------------------+ \ \
    //                          /  /           |  |          \  \ \ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
    //  slot: 0               /   | slot: 1    |  |           |   \              slot: 2    |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  |    radix_tree_node    | | |    radix_tree_node    | | |    radix_tree_node    |   |
    //  |   (kmem_cache#20-o0)  | | |   (kmem_cache#20-o2)  | | |   (kmem_cache#20-o3)  |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  | height: 1 | count: 64 | | | height: 1 | count: 64 | | | height: 1 | count: 64 |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  |    irq  0 ~ 63        | | |    irq 64 ~ 127       | | |    irq 128 ~ 191      |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //                           /                |            \                            |
    //  slot: 3                /    slot: 4       |              \                slot: 5    \                slot: 6
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |
    //  |   (kmem_cache#20-o4)  |   |   (kmem_cache#20-o5)  |   |   (kmem_cache#20-o6)  |   |   (kmem_cache#20-o7)  |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 32 |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  |    irq  192 ~ 255     |   |    irq 256 ~ 319      |   |    irq 320 ~ 383      |   |    irq 384 ~ 415      |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    */
    // irq 160...415까지의 struct irq_data에 값을 설정
    //
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->hwirq: 0...255
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->domain: kmem_cache#24-o0
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->state_use_accessors: 0x10800
    //
    // (kmem_cache#28-oX (irq 160...415))->irq_data.chip: &combiner_chip
    // (kmem_cache#28-oX (irq 160...415))->handle_irq: handle_level_irq
    // (kmem_cache#28-oX (irq 160...415))->name: NULL
    //
    // (kmem_cache#28-oX (irq 160...167))->irq_data.chip_data: &(kmem_cache#26-oX)[0] (combiner_data)
    // (kmem_cache#28-oX (irq 168...175))->irq_data.chip_data: &(kmem_cache#26-oX)[1] (combiner_data)
    // ......
    // (kmem_cache#28-oX (irq 408...415))->irq_data.chip_data: &(kmem_cache#26-oX)[31] (combiner_data)
    //
    // (kmem_cache#28-oX (irq 160...415))->status_use_accessors: 0x31600
    //
    // (kmem_cache#24-o0)->name: "COMBINER"
    // (kmem_cache#24-o0)->linear_revmap[0...255]: 160...415

    // combiner_irq_domain: kmem_cache#24-o0
    if (WARN_ON(!combiner_irq_domain)) {
        pr_warning("%s: irq domain init failed\n", __func__);
        return;
    }

    // max_nr: 32
    for (i = 0; i < max_nr; i++) {
        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, i: 0
        // irq_of_parse_and_map(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, 0): 32
        irq = irq_of_parse_and_map(np, i);
        // irq: 32

        // i: 0, &combiner_data[0], combiner_base: 0xf0004000, irq: 32
        combiner_init_one(&combiner_data[i], i,
                  combiner_base + (i >> 2) * 0x10, irq);

        // combiner_init_one에서 한일:
        // (&combiner_data[0])->base: 0xf0004000
        // (&combiner_data[0])->hwirq_offset: 0
        // (&combiner_data[0])->irq_mask: 0xff
        // (&combiner_data[0])->parent_irq: 32
        // group 0 의 interrupt disable 설정

        // i: 0, &combiner_data[0], irq: 32
        combiner_cascade_irq(&combiner_data[i], irq);

        // combiner_cascade_irq에서 한일:
        // (kmem_cache#28-oX (irq 32))->irq_data.handler_data: &combiner_data[0]
        // (kmem_cache#28-oX (irq 32))->handle_irq: combiner_handle_cascade_irq
        // (kmem_cache#28-oX (irq 32))->status_use_accessors: 0x31e00
        // (kmem_cache#28-oX (irq 32))->depth: 0
        // (&(kmem_cache#28-oX (irq 32))->irq_data)->state_use_accessors: 0x800
        //
        // register GICD_ISENABLER1 의 값을 세팅 하여 irq 32의 interrupt를 enable 시킴
    }
    // 루프 수행결과:

}
  • 루프 실행결과를 정리해 보면.
    • // (&combiner_data[0])->base: 0xf0004000
    • // (&combiner_data[0])->hwirq_offset: 0
    • // (&combiner_data[0])->irq_mask: 0xff
    • // (&combiner_data[0])->parent_irq: 32
    • // group 0 의 interrupt disable 설정
  • trap.c에 보면 memcpy로 vector와 stubs를 복제했다. stubs에 0x1000을 이후 위치부터 복사했다.
// ARM10C 20131109
__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, __vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq
  • IRQ가 걸리면, __vectors_start:로 가서 *o W(b) vector_irq
  • vectors_base()에서 vectors_high()가 1이면 0xffff0000로 처리한다.
  • vectors_high()가 참조하는 cr_alignement는
  • cr_alignment: 0x10c5387d, CR_V: (1 << 13)
  • 이고 여기서 13번째 비트는???
irq_hander를 .macro irq_handler를 찾아서 gic와 combiner을 설정하면서 만든 init_IRQ에서 이 핸들러를 등록했었다. set_handle_irq()에서 등록을 했었다.
vector_stub은 vm
## log
* 1st log

c9e1c12..5ce95d8 master -> origin/master Updating c9e1c12..5ce95d8 Fast-forward drivers/irqchip/exynos-combiner.c | 37 +++++++++++ drivers/irqchip/irq-gic.c | 37 +++++++++++ include/linux/irq.h | 20 ++++++ include/linux/irqchip/arm-gic.h | 1 + include/linux/irqdesc.h | 1 + kernel/irq/chip.c | 125 ++++++++++++++++++++++++++++++++++++-- kernel/irq/internals.h | 18 ++++++ kernel/irq/resend.c | 11 +++- kernel/irq/settings.h | 21 +++++++ 9 files changed, 266 insertions(+), 5 deletions(-)

* 2nd Log
5ce95d8..84d1280 master -> origin/master Updating 5ce95d8..84d1280 Fast-forward arch/arm/kernel/entry-armv.S | 40 ++++ arch/arm/kernel/vmlinux.lds.S | 5 + drivers/irqchip/exynos-combiner.c | 367 ++++++++++++++++++++++++++++++ drivers/irqchip/irqchip.c | 455 ++++++++++++++++++++++++++++++++++++++ drivers/of/irq.c | 262 +++++++++++++++++++++- init/main.c | 3 + mm/slub.c | 2 + 7 files changed, 1132 insertions(+), 2 deletions(-)

* 3th log

84d1280..1342489 master -> origin/master Updating 84d1280..1342489 Fast-forward drivers/irqchip/exynos-combiner.c | 6 +++--- drivers/irqchip/irqchip.c | 2 +- drivers/of/irq.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-)

2014년 12월 13일 토요일

[Linux Kernel] 82주차(2014.12.13)

ARM10C 82주차 후기

일시 : 2014.12.13 (82주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 2명

82주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree() *

main.c::start_kernel()

asmlinkage void __init start_kernel(void)
{
...
    setup_arch(&command_line);
...
    mm_init();
    // buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
    // pcpu 메모리, vmlist 는 slab으로 이관
...
    rcu_init();
    // rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
...
    /* init some links before init_ISA_irqs() */
    early_irq_init();
    // irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
    // allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

    init_IRQ();
  • call: start_kernel()->init_IRQ()
    • init_IRQ();

irq.c::init_IRQ()

  • called: start_kernel()->init_IRQ()
    • init_IRQ();
// ARM10C 20141004
void __init init_IRQ(void)
{
    // CONFIG_OF=y, machine_desc->init_irq: __mach_desc_EXYNOS5_DT.init_irq: 0
    if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
        irqchip_init();
    else
        machine_desc->init_irq();
}
  • call: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();
// ARM10C 20141004
extern struct of_device_id __irqchip_begin[];

// ARM10C 20141004
void __init irqchip_init(void)
{
    // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    of_irq_init(__irqchip_begin);
}
#ifdef CONFIG_IRQCHIP // CONFIG_IRQCHIP=y
#define IRQCHIP_OF_MATCH_TABLE()            \
    . = ALIGN(8);                           \
    VMLINUX_SYMBOL(__irqchip_begin) = .;    \
    *(__irqchip_of_table)                   \
    *(__irqchip_of_end)
#else
#define IRQCHIP_OF_MATCH_TABLE()
#endif
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);
void __init of_irq_init(const struct of_device_id *matches)
{
    struct device_node *np, *parent = NULL;
    // parent: NULL
    struct intc_desc *desc, *temp_desc;
    struct list_head intc_desc_list, intc_parent_list;

    INIT_LIST_HEAD(&intc_desc_list);
    // intc_desc_list 리스트 초기화 수행

    INIT_LIST_HEAD(&intc_parent_list);
    // intc_parent_list 리스트 초기화 수행

    // matches: irqchip_of_match_exynos4210_combiner
    for_each_matching_node(np, matches) {
    // for (np = of_find_matching_node(NULL, matches); np; np = of_find_matching_node(np, matches))

        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, "interrupt-controller", NULL):
        // combiner node의 "interrupt-controller" property의 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, "interrupt-controller", NULL):
        // gic node의 "interrupt-controller" property의 주소
        if (!of_find_property(np, "interrupt-controller", NULL))
            continue;
        /*
         * Here, we allocate and populate an intc_desc with the node
         * pointer, interrupt-parent device_node etc.
         */
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o10
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o11
        desc = kzalloc(sizeof(*desc), GFP_KERNEL);
        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11

        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11
        if (WARN_ON(!desc))
            goto err;

        // desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        desc->dev = np;
        // desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소): gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소): gic node 주소
        desc->interrupt_parent = of_irq_find_parent(np);
        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        if (desc->interrupt_parent == np)
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
            desc->interrupt_parent = NULL;
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL

        // &desc->list: &(kmem_cache#30-o10)->list
        // &desc->list: &(kmem_cache#30-o11)->list
        list_add_tail(&desc->list, &intc_desc_list);
        // intc_desc_list에 (kmem_cache#30-o10)->list를 tail에 추가
        // intc_desc_list에 (kmem_cache#30-o11)->list를 tail에 추가
    }

    // irqchip_of_match_exynos4210_combiner, irqchip_of_match_cortex_a15_gic 의
    // struct intc_desc 메모리 할당, intc_desc 맴버가 초기화 된 값이 intc_desc_list list의 tail로 추가됨

    // list_empty(&intc_desc_list): 0
    while (!list_empty(&intc_desc_list)) {
        list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
        // for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
        //  temp_desc = list_next_entry(desc, list);
        //      &desc->list != (&intc_desc_list);
        //      desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))

            // desc: kmem_cache#30-o10 (exynos4210_combiner), temp_desc: kmem_cache#30-o11 (cortex_a15_gic)
            // desc: kmem_cache#30-o11 (cortex_a15_gic), temp_desc: NULL

            const struct of_device_id *match;
            int ret;
            of_irq_init_cb_t irq_init_cb;

            // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소, parent: NULL
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL, parent: NULL
            if (desc->interrupt_parent != parent)
                continue;
                // continue 수행 (exynos4210_combiner)

            // &desc->list: (kmem_cache#30-o11)->list
            list_del(&desc->list);
            // intc_desc_list에서 (kmem_cache#30-o11)->list를 삭제

            // matches: irqchip_of_match_cortex_a15_gic,
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // of_match_node(cortex_a15_gic, devtree에서 allnext로 순회 하면서 찾은 gic node의 주소):
            // irqchip_of_match_cortex_a15_gic
            match = of_match_node(matches, desc->dev);
            // match: irqchip_of_match_cortex_a15_gic

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            if (WARN(!match->data,
                "of_irq_init: no init function for %s\n",
                match->compatible)) {
                kfree(desc);
                continue;
            }

            // match->compatible: irqchip_of_match_cortex_a15_gic.compatible: "arm,cortex-a15-gic",
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            pr_debug("of_irq_init: init %s @ %p, parent %p\n",
                 match->compatible,
                 desc->dev, desc->interrupt_parent);
            // "of_irq_init: init arm,cortex-a15-gic @ 0x(gic node의 주소), parent 0\n"

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            irq_init_cb = (of_irq_init_cb_t)match->data;
            // irq_init_cb: gic_of_init

            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소,
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            // gic_of_init(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, NULL):
            ret = irq_init_cb(desc->dev, desc->interrupt_parent);

            // ret: 0
            if (ret) {
                kfree(desc);
                continue;
            }
            /*
             * This one is now set up; add it to the parent list so
             * its children can get processed in a subsequent pass.
             */
            // &desc->list: &(kmem_cache#30-o11)->list
            list_add_tail(&desc->list, &intc_parent_list);
            // intc_parent_list에 tail로 &(kmem_cache#30-o11)->list를 추가
        }
        // &desc->list: &intc_desc_list 이므로  loop 탈출

        /* Get the next pending parent that might have children */
        // typeof(*desc): struct intc_desc
        // list_first_entry_or_null(&intc_parent_list, struct intc_desc, list):
        // (!list_empty(&intc_parent_list) ? list_first_entry(&intc_parent_list, struct intc_desc, list) : NULL)
        // list_first_entry(&intc_parent_list, struct intc_desc, list): kmem_cache#30-o11 (cortex_a15_gic)
        desc = list_first_entry_or_null(&intc_parent_list,
                        typeof(*desc), list);
        // desc: kmem_cache#30-o11 (cortex_a15_gic)

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        if (!desc) {
            pr_err("of_irq_init: children remain, but no parents\n");
            break;
        }

        // &desc->list: &(kmem_cache#30-o11 (cortex_a15_gic))->list
        list_del(&desc->list);
        // &(kmem_cache#30-o11 (cortex_a15_gic))->list에 연결된 list 삭제

        // parent: NULL
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        parent = desc->dev;
        // parent: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        kfree(desc);

log

  • 1st log
   43b267c..fc76100  master     -> origin/master
Updating 43b267c..fc76100
Fast-forward
arch/arm/include/asm/bitops.h         |   4 +
arch/arm/include/asm/hw_irq.h         |   2 +
arch/arm/kernel/irq.c                 |  22 ++-
arch/arm/lib/findbit.S                |   4 +
drivers/irqchip/exynos-combiner.c     | 129 ++++++++++++++-
drivers/irqchip/irq-gic.c             | 113 +++++++------
drivers/of/base.c                     |   1 +
drivers/of/irq.c                      | 184 ++++++++++++++++++++-
include/linux/irq.h                   |  27 ++++
include/linux/irqdomain.h             |   1 +
include/linux/list.h                  |   5 +
include/linux/of.h                    |  10 ++
include/linux/of_irq.h                |   7 +-
include/linux/types.h                 |   1 +
include/uapi/asm-generic/errno-base.h |   2 +
kernel/irq/chip.c                     |  85 +++++++++-
kernel/irq/internals.h                |  10 ++
kernel/irq/irqdesc.c                  | 293 ++++++++++++++++++++++------------
kernel/irq/irqdomain.c                | 246 ++++++++++++++++++++++++++--
lib/bitmap.c                          |  32 ++++
20 files changed, 1003 insertions(+), 175 deletions(-)
  • 2nd log
   fc76100..0ba901e  master     -> origin/master
Updating fc76100..0ba901e
Fast-forward
drivers/irqchip/exynos-combiner.c | 110 +++++++++++++++++++++++++++----------
kernel/irq/irqdesc.c              | 112 +++++++++++++++++++++++++++-----------
kernel/irq/irqdomain.c            | 112 +++++++++++++++++++++++++++-----------
3 files changed, 242 insertions(+), 92 deletions(-)

2014년 12월 10일 수요일

OpenStack Juno 정리

OpenStack Juno 릴리즈 정리

  • OpenStack은 매해 두번씩 새로운 버전이 릴리즈합니다.(4월, 10월)
  • 최신 안정판: 2014.2 (Juno)
  • 다음 안정판: 2015.1 (Kilo)

Juno (2014.2)

  • Juno는 미국 조지아주 아틀란타시 근교에 지명

  • 개발기간: 2014/5 ~ 2014/10
  • 개발항목: 340개소 이상
  • 버그수정: 약 3200개이상
  • 스택수 : 11개
    • Data Processing (Sahara) 추가
  • 5대 기여사 (Contribution Company)
    • 1. 20% HP
    • 2. 18% RedHat
    • 3. 13% Mirantis
    • 4. 10% Rackspace
    • 5.   8% IBM

OpenStack 정식 스텍 리스트

  • Swift : Object Storage 클라우드 스토리지
  • Nova : Compute 클라우드 컴퓨팅
  • Glance : Image Service 가상머신 템플릿 관리
  • Keystone : Identity 종합 사용자/테넌트등 인증
  • Horizon : Dashboard 사용자 서비스 포털
  • Neutron : Networking 클라우드 네트워크 가상화 관리
  • Cinder : Block Storage 볼륨 스토리지
  • Ceilometer: Telemetry 자원 모니터링, 운영 감시
  • Heat : Orchestration 클라우드 오케스트레이션
  • Trove : Database 클라우드 데이터베이스 DBaaS
  • Sahara : Data Processing 빅데이터 처리

OpenStack 육성 프로젝트

  • Ironic : Baremetal 물리머신 관리
  • Zaqar : Queue service (MQaaS)
  • Barbican : Key management 키 데이터 관리
  • Desinate : DNS service (DNSaaS)
  • Oslo : Common Libraries 각 프로젝트 공통 코드
  • TripleO : Deployment
  • Devstack : 개발자용 OpenStack 설치

Juno에서 추가된 새로운 기능들

  • Nova
    • RBAC
    • Evacuate Host
    • Console 개선
    • Flavor 추가 속성
    • Host metering
  • Glance
    • Image meta data 대응,
    • tag 대응
  • Neutron
    • RBAC
    • DVR/L3-HA
    • IPv6서브넷 대응
    • 프로바이더 네트워크 대응
  • Heat
    • RBAC
    • 스택 페이징
  • Cinder
    • 볼륨 형식 변경
    • 볼륨 확장 속성
    • 볼륨 QoS 속성
  • Keystone
    • RBAC 대응 사용자 환경
    • 사용자/도메인간 룰 추가
  • Trove
    • 증분 백업
  • Sahara
    • 전용 사용자 환경 추가 (Horizon)
    • 프로세스가 실행되는 대상에 대한 링크 추가